Freeciv-3.2
Loading...
Searching...
No Matches
ruleset.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 "achievements.h"
36#include "actions.h"
37#include "ai.h"
38#include "base.h"
39#include "capability.h"
40#include "city.h"
41#include "counters.h"
42#include "effects.h"
43#include "extras.h"
44#include "fc_types.h"
45#include "featured_text.h"
46#include "game.h"
47#include "government.h"
48#include "map.h"
49#include "movement.h"
50#include "multipliers.h"
51#include "name_translation.h"
52#include "nation.h"
53#include "packets.h"
54#include "player.h"
55#include "requirements.h"
56#include "rgbcolor.h"
57#include "road.h"
58#include "sex.h"
59#include "specialist.h"
60#include "style.h"
61#include "tech.h"
62#include "traderoutes.h"
63#include "unit.h"
64#include "unittype.h"
65
66/* server */
67#include "citytools.h"
68#include "notify.h"
69#include "plrhand.h"
70#include "rscompat.h"
71#include "rssanity.h"
72#include "settings.h"
73#include "srv_main.h"
74
75/* server/advisors */
76#include "advruleset.h"
77
78/* server/scripting */
79#include "script_server.h"
80
81#include "ruleset.h"
82
83/* RULESET_SUFFIX already used, no leading dot here */
84#define RULES_SUFFIX "ruleset"
85#define SCRIPT_SUFFIX "lua"
86
87#define ADVANCE_SECTION_PREFIX "advance_"
88#define TECH_CLASS_SECTION_PREFIX "techclass_"
89#define BUILDING_SECTION_PREFIX "building_"
90#define CITYSTYLE_SECTION_PREFIX "citystyle_"
91#define MUSICSTYLE_SECTION_PREFIX "musicstyle_"
92#define UEFF_SECTION_PREFIX "ueff_"
93#define EFFECT_SECTION_PREFIX "effect_"
94#define GOVERNMENT_SECTION_PREFIX "government_"
95#define NATION_SET_SECTION_PREFIX "nset" /* without underscore? */
96#define NATION_GROUP_SECTION_PREFIX "ngroup" /* without underscore? */
97#define NATION_SECTION_PREFIX "nation" /* without underscore? */
98#define STYLE_SECTION_PREFIX "style_"
99#define CLAUSE_SECTION_PREFIX "clause_"
100#define EXTRA_SECTION_PREFIX "extra_"
101#define BASE_SECTION_PREFIX "base_"
102#define ROAD_SECTION_PREFIX "road_"
103#define RESOURCE_SECTION_PREFIX "resource_"
104#define GOODS_SECTION_PREFIX "goods_"
105#define SPECIALIST_SECTION_PREFIX "specialist_"
106#define TERRAIN_SECTION_PREFIX "terrain_"
107#define UNIT_CLASS_SECTION_PREFIX "unitclass_"
108#define UNIT_SECTION_PREFIX "unit_"
109#define DISASTER_SECTION_PREFIX "disaster_"
110#define ACHIEVEMENT_SECTION_PREFIX "achievement_"
111#define ACTION_ENABLER_SECTION_PREFIX "actionenabler_"
112#define MULTIPLIER_SECTION_PREFIX "multiplier_"
113#define COUNTER_SECTION_PREFIX "counter_"
114
115#define check_name(name) (check_strlen(name, MAX_LEN_NAME, NULL))
116#define check_cityname(name) (check_strlen(name, MAX_LEN_CITYNAME, NULL))
117
118/* avoid re-reading files */
119static const char name_too_long[] = "Name \"%s\" too long; truncating.";
120#define MAX_SECTION_LABEL 64
121#define section_strlcpy(dst, src) \
122 (void) loud_strlcpy(dst, src, MAX_SECTION_LABEL, name_too_long)
123static char *resource_sections = NULL;
124static char *terrain_sections = NULL;
125static char *extra_sections = NULL;
126static char *base_sections = NULL;
127static char *road_sections = NULL;
128
130
131static bool load_rulesetdir(const char *rsdir, bool compat_mode,
133 bool act, bool buffer_script, bool load_luadata);
134static struct section_file *openload_ruleset_file(const char *whichset,
135 const char *rsdir);
136
137static bool load_game_names(struct section_file *file,
138 struct rscompat_info *compat);
139static bool load_action_names(struct section_file *file,
140 struct rscompat_info *compat);
141static bool load_tech_names(struct section_file *file,
142 struct rscompat_info *compat);
143static bool load_unit_names(struct section_file *file,
144 struct rscompat_info *compat);
145static bool load_building_names(struct section_file *file,
146 struct rscompat_info *compat);
147static bool load_government_names(struct section_file *file,
148 struct rscompat_info *compat);
149static bool load_terrain_names(struct section_file *file,
150 struct rscompat_info *compat);
151static bool load_style_names(struct section_file *file,
152 struct rscompat_info *compat);
153static bool load_nation_names(struct section_file *file,
154 struct rscompat_info *compat);
155static bool load_city_name_list(struct section_file *file,
156 struct nation_type *pnation,
157 const char *secfile_str1,
158 const char *secfile_str2,
159 const char **allowed_terrains,
160 size_t atcount);
161
162static bool load_ruleset_techs(struct section_file *file,
163 struct rscompat_info *compat);
164static bool load_ruleset_units(struct section_file *file,
165 struct rscompat_info *compat);
166static bool load_ruleset_buildings(struct section_file *file,
167 struct rscompat_info *compat);
168static bool load_ruleset_governments(struct section_file *file,
169 struct rscompat_info *compat);
170static bool load_ruleset_terrain(struct section_file *file,
171 struct rscompat_info *compat);
172static bool load_ruleset_styles(struct section_file *file,
173 struct rscompat_info *compat);
174static bool load_ruleset_cities(struct section_file *file,
175 struct rscompat_info *compat);
176static bool load_ruleset_effects(struct section_file *file,
177 struct rscompat_info *compat);
178static bool load_ruleset_game(struct section_file *file, bool act,
179 struct rscompat_info *compat);
180static bool load_ruleset_actions(struct section_file *file,
181 struct section_file *gamefile,
182 struct rscompat_info *compat);
183
184static void send_ruleset_tech_classes(struct conn_list *dest);
185static void send_ruleset_techs(struct conn_list *dest);
186static void send_ruleset_unit_classes(struct conn_list *dest);
187static void send_ruleset_units(struct conn_list *dest);
188static void send_ruleset_buildings(struct conn_list *dest);
189static void send_ruleset_terrain(struct conn_list *dest);
190static void send_ruleset_resources(struct conn_list *dest);
191static void send_ruleset_extras(struct conn_list *dest);
192static void send_ruleset_bases(struct conn_list *dest);
193static void send_ruleset_roads(struct conn_list *dest);
194static void send_ruleset_goods(struct conn_list *dest);
195static void send_ruleset_governments(struct conn_list *dest);
196static void send_ruleset_styles(struct conn_list *dest);
197static void send_ruleset_clauses(struct conn_list *dest);
198static void send_ruleset_musics(struct conn_list *dest);
199static void send_ruleset_cities(struct conn_list *dest);
200static void send_ruleset_game(struct conn_list *dest);
201static void send_ruleset_team_names(struct conn_list *dest);
202
203static bool load_ruleset_veteran(struct section_file *file,
204 const char *path,
205 struct veteran_system **vsystem, char *err,
206 size_t err_len);
207
210
211/**********************************************************************/
216 const char *file, const char *function,
217 int line, enum log_level level,
218 const char *format, ...)
219{
220 va_list args;
221 char buf[MAX_LEN_LOG_LINE];
222
223 if (logger == NULL && !log_do_output_for_level(level)) {
224 return;
225 }
226
227 va_start(args, format);
228 if (logger != NULL) {
229 fc_vsnprintf(buf, sizeof(buf), format, args);
230 logger(buf);
231 } else {
232 vdo_log(file, function, line, FALSE, level, buf, sizeof(buf), format, args);
233 }
234 va_end(args);
235
236 if (LOG_FATAL >= level) {
238 }
239}
240
241/**********************************************************************/
245{
246 int purged = 0;
247
248 action_iterate(act_id) {
249 struct action *paction = action_by_number(act_id);
250
252 == 0) {
253 /* Not relevant. */
254 continue;
255 }
256
257 /* Impossible hard requirement. */
259 /* Make sure that all action enablers are disabled. */
261 ae) {
262 ae->ruledit_disabled = TRUE;
263 purged++;
265
266 log_normal("Purged all action enablers for %s",
268 }
269
270 /* Impossible requirement vector requirement. */
272 ae) {
273 if (!ae->ruledit_disabled
275 || req_vec_is_impossible_to_fulfill(&ae->target_reqs))) {
276 ae->ruledit_disabled = TRUE;
277 purged++;
278 log_normal("Purged unused action enabler for %s",
280 }
283
284 return purged;
285}
286
287/**********************************************************************/
291{
292 int purged = 0;
293 enum effect_type type;
294
299 eft->rulesave.do_not_save = TRUE;
300 purged++;
301 log_normal("Purged unused effect for %s",
302 effect_type_name(eft->type));
303 }
305 }
306
307 return purged;
308}
309
310/**********************************************************************/
314{
315 int purged = 0;
316
319
320 return purged;
321}
322
323/**********************************************************************/
328 const char *msg)
329{
330 struct req_vec_problem *problem;
331 bool result;
332
334 reqs);
335
336 if (problem == NULL) {
337 /* No problem. */
338 return FALSE;
339 }
340
341 if (problem->num_suggested_solutions == 0) {
342 /* No solution. */
344 return FALSE;
345 }
346
347 if (problem->num_suggested_solutions == 1
348 && problem->suggested_solutions[0].operation == RVCO_REMOVE) {
349 /* Remove !present req that never is there. */
350 log_normal("%s", msg);
351 result = req_vec_change_apply(&problem->suggested_solutions[0],
354 return result;
355 }
356
357 /* Not handled. Don't know what this is. */
358 fc_assert(problem->num_suggested_solutions == 1);
360 return FALSE;
361}
362
363/**********************************************************************/
368 const char *msg)
369{
370 struct req_vec_problem *problem;
371 bool result;
372
374 reqs);
375
376 if (problem == NULL) {
377 /* No problem. */
378 return FALSE;
379 }
380
381 if (problem->num_suggested_solutions == 0) {
382 /* No solution. */
384 return FALSE;
385 }
386
387 if (problem->num_suggested_solutions == 2
388 && problem->suggested_solutions[0].operation == RVCO_REMOVE
389 && problem->suggested_solutions[1].operation == RVCO_REMOVE
390 && are_requirements_equal(&problem->suggested_solutions[0].req,
391 &problem->suggested_solutions[1].req)) {
392 /* Simple duplication is handled. */
393 log_normal("%s", msg);
394 result = req_vec_change_apply(&problem->suggested_solutions[1],
397 return result;
398 }
399
400 /* Requirements of different kinds making each other redundant isn't
401 * supported yet. It could be done by always removing the most general
402 * requirement. So unit type is kept when redundant with unit flag, unit
403 * class and unit class flag etc. */
405 return FALSE;
406}
407
408/**********************************************************************/
413 const char *msg)
414{
415 return (purge_unused_req_vec(reqs, msg)
417}
418
419/**********************************************************************/
424{
425 int purged = 0;
426
427 action_iterate(act_id) {
428 struct action *paction = action_by_number(act_id);
429 char actor_reqs[MAX_LEN_NAME * 2];
430 char target_reqs[MAX_LEN_NAME * 2];
431
432 /* Error log text */
433 fc_snprintf(actor_reqs, sizeof(actor_reqs),
434 "Purged redundant requirement in"
435 " %s in action enabler for %s",
436 "actor_reqs", action_rule_name(paction));
437 fc_snprintf(target_reqs, sizeof(target_reqs),
438 "Purged redundant requirement in"
439 " %s in action enabler for %s",
440 "target_reqs", action_rule_name(paction));
441
442 /* Do the purging. */
444 ae) {
445 while (!ae->ruledit_disabled
446 && (purge_redundant_req_vec(&ae->actor_reqs, actor_reqs)
447 || purge_redundant_req_vec(&ae->target_reqs,
448 target_reqs))) {
449 purged++;
450 }
453
454 return purged;
455}
456
457/**********************************************************************/
462{
463 int purged = 0;
464 enum effect_type type;
465
468 char msg[MAX_LEN_NAME * 2];
469
470 /* Error log text */
471 fc_snprintf(msg, sizeof(msg),
472 "Purged redundant requirement in effect of type %s",
474
475 /* Do the purging. */
477 while (purge_redundant_req_vec(&eft->reqs, msg)) {
478 purged++;
479 }
481 }
482
483 return purged;
484}
485
486/**********************************************************************/
491{
492 int purged = 0;
493
496
497 if (purged > 0) {
498 /* An unused requirement may be an obligatory hard requirement. */
500 }
501
502 return purged;
503}
504
505/**********************************************************************/
509static const char *valid_ruleset_filename(const char *subdir,
510 const char *name,
511 const char *extension,
512 bool optional)
513{
514 char filename[512];
515 const char *dfilename;
516
518
519 fc_snprintf(filename, sizeof(filename), "%s" DIR_SEPARATOR "%s.%s",
521 log_verbose("Trying \"%s\".", filename);
522 dfilename = fileinfoname(get_data_dirs(), filename);
523 if (dfilename) {
524 return dfilename;
525 }
526
527 fc_snprintf(filename, sizeof(filename), "default" DIR_SEPARATOR "%s.%s", name, extension);
528 log_verbose("Trying \"%s\": default ruleset directory.", filename);
529 dfilename = fileinfoname(get_data_dirs(), filename);
530 if (dfilename) {
531 return dfilename;
532 }
533
534 fc_snprintf(filename, sizeof(filename), "%s_%s.%s",
536 log_verbose("Trying \"%s\": alternative ruleset filename syntax.",
537 filename);
538 dfilename = fileinfoname(get_data_dirs(), filename);
539 if (dfilename) {
540 return dfilename;
541 } else if (!optional) {
543 /* TRANS: message about an installation error. */
544 _("Could not find a readable \"%s.%s\" ruleset file."),
545 name, extension);
546 }
547
548 return NULL;
549}
550
551/**********************************************************************/
555{
556 return script_buffer;
557}
558
559/**********************************************************************/
563{
564 return parser_buffer;
565}
566
567/**********************************************************************/
571static struct section_file *openload_ruleset_file(const char *whichset,
572 const char *rsdir)
573{
574 char sfilename[512];
577 struct section_file *secfile;
578
579 if (dfilename == NULL) {
580 return NULL;
581 }
582
583 /* Need to save a copy of the filename for following message, since
584 section_file_load() may call datafilename() for includes. */
586 secfile = secfile_load(sfilename, FALSE);
587
588 if (secfile == NULL) {
589 ruleset_error(NULL, LOG_ERROR, "Could not load ruleset '%s':\n%s",
591 }
592
593 return secfile;
594}
595
596/**********************************************************************/
599static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir,
600 char **buffer, bool optional)
601{
604
605 if (dfilename == NULL) {
606 return optional ? TRI_MAYBE : TRI_NO;
607 }
608
609 if (buffer == NULL) {
611 ruleset_error(NULL, LOG_ERROR, "\"%s\": could not load ruleset script.",
612 dfilename);
613
614 return TRI_NO;
615 }
616 } else {
618 }
619
620 return TRI_YES;
621}
622
623/**********************************************************************/
626static struct section_file *openload_luadata_file(const char *rsdir)
627{
628 struct section_file *secfile;
629 char sfilename[512];
630 const char *dfilename = valid_ruleset_filename(rsdir, "luadata",
631 "txt", TRUE);
632
633 if (dfilename == NULL) {
634 return NULL;
635 }
636
637 /* Need to save a copy of the filename for following message, since
638 section_file_load() may call datafilename() for includes. */
640 secfile = secfile_load(sfilename, FALSE);
641
642 if (secfile == NULL) {
643 ruleset_error(NULL, LOG_ERROR, "Could not load luadata '%s':\n%s",
645 }
646
647 return secfile;
648}
649
650/**********************************************************************/
655 struct rscompat_info *compat,
656 const char *sec,
657 const char *sub,
658 const char *rfor)
659{
660 const char *type, *name;
661 int j;
662 const char *filename;
663
664 filename = secfile_name(file);
665
667
668 for (j = 0; (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
669 sec, sub, j)); j++) {
670 char buf[MAX_LEN_NAME];
671 const char *range;
672 bool survives, present, quiet;
673 struct entry *pentry;
674 struct requirement req;
675
676 if (!(pentry = secfile_entry_lookup(file, "%s.%s%d.name",
677 sec, sub, j))) {
679
680 return NULL;
681 }
682 name = NULL;
683 switch (entry_type_get(pentry)) {
684 case ENTRY_BOOL:
685 {
686 bool val;
687
688 if (entry_bool_get(pentry, &val)) {
689 fc_snprintf(buf, sizeof(buf), "%d", val);
690 name = buf;
691 }
692 }
693 break;
694 case ENTRY_INT:
695 {
696 int val;
697
698 if (entry_int_get(pentry, &val)) {
699 fc_snprintf(buf, sizeof(buf), "%d", val);
700 name = buf;
701 }
702 }
703 break;
704 case ENTRY_STR:
706 break;
707 case ENTRY_FLOAT:
710 "\"%s\": trying to have an floating point entry as a requirement name in '%s.%s%d'.",
711 filename, sec, sub, j);
712 break;
715 break;
718 break;
719 case ENTRY_ILLEGAL:
721 break;
722 }
723 if (NULL == name) {
725 "\"%s\": error in handling requirement name for '%s.%s%d'.",
726 filename, sec, sub, j);
727 return NULL;
728 }
729
730 if (!(range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j))) {
732
733 return NULL;
734 }
735
736 if (compat->compat_mode) {
738 }
739
740 survives = FALSE;
741 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.survives",
742 sec, sub, j))
745 "\"%s\": invalid boolean value for survives for "
746 "'%s.%s%d'.", filename, sec, sub, j);
747 }
748
749 present = TRUE;
750 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.present",
751 sec, sub, j))
754 "\"%s\": invalid boolean value for present for "
755 "'%s.%s%d'.", filename, sec, sub, j);
756 }
757 quiet = FALSE;
758 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.quiet",
759 sec, sub, j))
760 && !entry_bool_get(pentry, &quiet)) {
762 "\"%s\": invalid boolean value for quiet for "
763 "'%s.%s%d'.", filename, sec, sub, j);
764 }
765
766 if (compat->compat_mode) {
768 }
769
771 if (req.source.kind == universals_n_invalid()) {
773 "\"%s\" [%s] has invalid or unknown req: "
774 "\"%s\" \"%s\".",
775 filename, sec, type, name);
776
777 return NULL;
778 }
779
781 }
782
783 if (j > MAX_NUM_REQS) {
785 "Too many (%d) requirements for %s. Max is %d",
786 j, rfor, MAX_NUM_REQS);
787
788 return NULL;
789 }
790
791 return &reqs_list;
792}
793
794/**********************************************************************/
798 struct section_file *file,
799 const char *sec,
800 const char *sub)
801{
802 const char *flag;
803 int j;
804 const char *filename;
805 bool success = TRUE;
806
807 filename = secfile_name(file);
808
809 for (j = 0; (flag = secfile_lookup_str_default(file, NULL, "%s.%s%d.flag",
810 sec, sub, j)); j++) {
811 struct combat_bonus *bonus = fc_malloc(sizeof(*bonus));
812 const char *type;
813
815 if (!unit_type_flag_id_is_valid(bonus->flag)) {
816 log_error("\"%s\": unknown flag name \"%s\" in '%s.%s'.",
817 filename, flag, sec, sub);
818 FC_FREE(bonus);
819 success = FALSE;
820 continue;
821 }
822 type = secfile_lookup_str(file, "%s.%s%d.type", sec, sub, j);
824 if (!combat_bonus_type_is_valid(bonus->type)) {
825 log_error("\"%s\": unknown bonus type \"%s\" in '%s.%s'.",
826 filename, type, sec, sub);
827 FC_FREE(bonus);
828 success = FALSE;
829 continue;
830 }
831 if (!secfile_lookup_int(file, &bonus->value, "%s.%s%d.value",
832 sec, sub, j)) {
833 log_error("\"%s\": failed to get value from '%s.%s%d'.",
834 filename, sec, sub, j);
835 FC_FREE(bonus);
836 success = FALSE;
837 continue;
838 }
840 "%s.%s%d.quiet",
841 sec, sub, j);
843 }
844
845 return success;
846}
847
848/**********************************************************************/
856static bool lookup_tech(struct section_file *file,
857 struct advance **result,
858 const char *prefix, const char *entry,
859 const char *filename,
860 const char *description)
861{
862 const char *sval;
863
864 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
865 if (!sval || !strcmp(sval, "Never")) {
866 *result = A_NEVER;
867 } else {
868 *result = advance_by_rule_name(sval);
869
870 if (A_NEVER == *result) {
872 "\"%s\" %s %s: couldn't match \"%s\".",
873 filename, (description ? description : prefix), entry, sval);
874 return FALSE;
875 }
876 }
877
878 return TRUE;
879}
880
881/**********************************************************************/
888static bool lookup_building(struct section_file *file,
889 const char *prefix, const char *entry,
890 struct impr_type **result,
891 const char *filename,
892 const char *description)
893{
894 const char *sval;
895 bool ok = TRUE;
896
897 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
898 if (!sval || strcmp(sval, "None") == 0) {
899 *result = B_NEVER;
900 } else {
902
903 if (B_NEVER == *result) {
905 "\"%s\" %s %s: couldn't match \"%s\".",
906 filename, (description ? description : prefix), entry, sval);
907 ok = FALSE;
908 }
909 }
910
911 return ok;
912}
913
914/**********************************************************************/
921static bool lookup_unit_list(struct section_file *file, const char *prefix,
922 const char *entry,
923 struct unit_type **output,
924 const char *filename)
925{
926 const char **slist;
927 size_t nval;
928 int i;
929 bool ok = TRUE;
930
931 /* pre-fill with NULL: */
932 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
933 output[i] = NULL;
934 }
935 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
936 if (nval == 0) {
937 /* 'No vector' is considered same as empty vector */
938 if (slist != NULL) {
939 free(slist);
940 }
941 return TRUE;
942 }
943 if (nval > MAX_NUM_UNIT_LIST) {
945 "\"%s\": string vector %s.%s too long (%d, max %d)",
946 filename, prefix, entry, (int) nval, MAX_NUM_UNIT_LIST);
947 ok = FALSE;
948 } else if (nval == 1 && strcmp(slist[0], "") == 0) {
949 free(slist);
950 return TRUE;
951 }
952 if (ok) {
953 for (i = 0; i < nval; i++) {
954 const char *sval = slist[i];
956
957 if (!punittype) {
959 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
960 filename, prefix, entry, i, sval);
961 ok = FALSE;
962 break;
963 }
964 output[i] = punittype;
965 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
967 }
968 }
969 free(slist);
970
971 return ok;
972}
973
974/**********************************************************************/
981static bool lookup_tech_list(struct section_file *file, const char *prefix,
982 const char *entry, int *output,
983 const char *filename)
984{
985 const char **slist;
986 size_t nval;
987 int i;
988 bool ok = TRUE;
989
990 /* pre-fill with A_LAST: */
991 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
992 output[i] = A_LAST;
993 }
994 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
995 if (slist == NULL || nval == 0) {
996 return TRUE;
997 } else if (nval > MAX_NUM_TECH_LIST) {
999 "\"%s\": string vector %s.%s too long (%d, max %d)",
1000 filename, prefix, entry, (int) nval, MAX_NUM_TECH_LIST);
1001 ok = FALSE;
1002 }
1003
1004 if (ok) {
1005 if (nval == 1 && strcmp(slist[0], "") == 0) {
1006 FC_FREE(slist);
1007 return TRUE;
1008 }
1009 for (i = 0; i < nval && ok; i++) {
1010 const char *sval = slist[i];
1012
1013 if (NULL == padvance) {
1015 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1016 filename, prefix, entry, i, sval);
1017 ok = FALSE;
1018 }
1019 if (!valid_advance(padvance)) {
1021 "\"%s\" %s.%s (%d): \"%s\" is removed.",
1022 filename, prefix, entry, i, sval);
1023 ok = FALSE;
1024 }
1025
1026 if (ok) {
1027 output[i] = advance_number(padvance);
1028 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
1030 }
1031 }
1032 }
1033 FC_FREE(slist);
1034
1035 return ok;
1036}
1037
1038/**********************************************************************/
1045static bool lookup_building_list(struct section_file *file,
1046 const char *prefix, const char *entry,
1047 int *output, const char *filename)
1048{
1049 const char **slist;
1050 size_t nval;
1051 int i;
1052 bool ok = TRUE;
1053
1054 /* pre-fill with B_LAST: */
1055 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
1056 output[i] = B_LAST;
1057 }
1058 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
1061 "\"%s\": string vector %s.%s too long (%d, max %d)",
1062 filename, prefix, entry, (int) nval, MAX_NUM_BUILDING_LIST);
1063 ok = FALSE;
1064 } else if (nval == 0 || (nval == 1 && strcmp(slist[0], "") == 0)) {
1065 if (slist != NULL) {
1066 FC_FREE(slist);
1067 }
1068 return TRUE;
1069 }
1070 if (ok) {
1071 for (i = 0; i < nval; i++) {
1072 const char *sval = slist[i];
1073 struct impr_type *pimprove = improvement_by_rule_name(sval);
1074
1075 if (NULL == pimprove) {
1077 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1078 filename, prefix, entry, i, sval);
1079 ok = FALSE;
1080 break;
1081 }
1082 output[i] = improvement_number(pimprove);
1083 log_debug("%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
1084 }
1085 }
1086 free(slist);
1087
1088 return ok;
1089}
1090
1091/**********************************************************************/
1097static bool lookup_unit_type(struct section_file *file,
1098 const char *prefix,
1099 const char *entry,
1100 const struct unit_type **result,
1101 const char *filename,
1102 const char *description)
1103{
1104 const char *sval;
1105
1106 sval = secfile_lookup_str_default(file, "None", "%s.%s", prefix, entry);
1107
1108 if (strcmp(sval, "None") == 0) {
1109 *result = NULL;
1110 } else {
1111 *result = unit_type_by_rule_name(sval);
1112 if (*result == NULL) {
1114 "\"%s\" %s %s: couldn't match \"%s\".",
1115 filename, (description ? description : prefix), entry, sval);
1116
1117 return FALSE;
1118 }
1119 }
1120
1121 return TRUE;
1122}
1123
1124/**********************************************************************/
1128static struct government *lookup_government(struct section_file *file,
1129 const char *entry,
1130 const char *filename,
1131 struct government *fallback)
1132{
1133 const char *sval;
1134 struct government *gov;
1135
1136 sval = secfile_lookup_str_default(file, NULL, "%s", entry);
1137 if (!sval) {
1138 gov = fallback;
1139 } else {
1141 }
1142 if (!gov) {
1144 "\"%s\" %s: couldn't match \"%s\".",
1145 filename, entry, sval);
1146 }
1147 return gov;
1148}
1149
1150/**********************************************************************/
1153static char *lookup_string(struct section_file *file, const char *prefix,
1154 const char *suffix)
1155{
1156 const char *sval = secfile_lookup_str(file, "%s.%s", prefix, suffix);
1157
1158 if (NULL != sval) {
1159 char copy[strlen(sval) + 1];
1160
1161 strcpy(copy, sval);
1163 if (strlen(copy) > 0) {
1164 return fc_strdup(copy);
1165 }
1166 }
1167 return NULL;
1168}
1169
1170/**********************************************************************/
1173static struct strvec *lookup_strvec(struct section_file *file,
1174 const char *prefix, const char *suffix)
1175{
1176 size_t dim;
1177 const char **vec = secfile_lookup_str_vec(file, &dim,
1178 "%s.%s", prefix, suffix);
1179
1180 if (NULL != vec) {
1181 struct strvec *dest = strvec_new();
1182
1183 strvec_store(dest, vec, dim);
1184 free(vec);
1185 return dest;
1186 }
1187 return NULL;
1188}
1189
1190/**********************************************************************/
1193static struct extra_type *lookup_resource(const char *filename,
1194 const char *name,
1195 const char *jsection)
1196{
1197 struct extra_type *pres;
1198
1200
1201 if (pres == NULL) {
1203 "\"%s\" [%s] has unknown \"%s\".",
1204 filename, jsection, name);
1205 }
1206
1207 return pres;
1208}
1209
1210/**********************************************************************/
1214static bool lookup_terrain(struct section_file *file,
1215 const char *entry,
1216 const char *filename,
1217 struct terrain *pthis,
1218 struct terrain **result,
1219 bool null_acceptable)
1220{
1221 const int j = terrain_index(pthis);
1222 const char *jsection = &terrain_sections[j * MAX_SECTION_LABEL];
1223 const char *name = secfile_lookup_str(file, "%s.%s", jsection, entry);
1224 struct terrain *pterr;
1225
1226 if (NULL == name && !null_acceptable) {
1227 return FALSE;
1228 }
1229
1230 if (NULL == name
1231 || *name == '\0'
1232 || (0 == strcmp(name, "none"))
1233 || (0 == strcmp(name, "no"))) {
1234 *result = T_NONE;
1235
1236 return TRUE;
1237 }
1238 if (0 == strcmp(name, "yes")) {
1239 *result = pthis;
1240
1241 return TRUE;
1242 }
1243
1245 *result = pterr;
1246
1247 if (pterr == NULL) {
1249 "\"%s\" [%s] has unknown \"%s\".",
1250 secfile_name(file), jsection, name);
1251 return FALSE;
1252 }
1253
1254 return TRUE;
1255}
1256
1257/**********************************************************************/
1264bool lookup_time(const struct section_file *secfile, int *turns,
1265 const char *sec_name, const char *property_name,
1266 const char *filename, const char *item_name,
1267 bool *ok)
1268{
1269 /* Assumes that PACKET_UNIT_INFO.activity_count in packets.def is UINT16 */
1270 const int max_turns = 65535 / ACTIVITY_FACTOR;
1271
1272 if (!secfile_lookup_int(secfile, turns, "%s.%s", sec_name, property_name)) {
1273 return FALSE;
1274 }
1275
1276 if (*turns > max_turns) {
1278 "\"%s\": \"%s\": \"%s\" value %d too large (max %d)",
1279 filename, item_name ? item_name : sec_name,
1280 property_name, *turns, max_turns);
1281 *ok = FALSE;
1282 }
1283
1284 return TRUE; /* we found _something */
1285}
1286
1287/**********************************************************************/
1291 const char *domain,
1292 struct section_file *file,
1293 const char *sec_name)
1294{
1295 const char *name = secfile_lookup_str(file, "%s.name", sec_name);
1296 const char *rule_name = secfile_lookup_str(file, "%s.rule_name", sec_name);
1297
1298 if (!name) {
1300 "\"%s\" [%s]: no \"name\" specified.",
1301 secfile_name(file), sec_name);
1302 return FALSE;
1303 }
1304
1305 names_set(pname, domain, name, rule_name);
1306
1307 return TRUE;
1308}
1309
1310/**********************************************************************/
1314 struct section_file *file,
1315 const char *secname, const char *field_prefix)
1316{
1317 enum trait tr;
1318
1319 /* FIXME: Use specenum trait names without duplicating them here.
1320 * Just needs to take care of case.
1321 * This list is also duplicated in rulesave.c:save_traits() */
1322 const char *trait_names[] = {
1323 "expansionist",
1324 "trader",
1325 "aggressive",
1326 "builder",
1327 NULL
1328 };
1329
1330 for (tr = trait_begin(); tr != trait_end() && trait_names[tr] != NULL; tr = trait_next(tr)) {
1331 out[tr].min = secfile_lookup_int_default(file, -1, "%s.%s%s_min",
1332 secname,
1334 trait_names[tr]);
1335 out[tr].max = secfile_lookup_int_default(file, -1, "%s.%s%s_max",
1336 secname,
1338 trait_names[tr]);
1339 out[tr].fixed = secfile_lookup_int_default(file, -1, "%s.%s%s_default",
1340 secname,
1342 trait_names[tr]);
1343 }
1344
1345 fc_assert(tr == trait_end()); /* number of trait_names correct */
1346}
1347
1348/**********************************************************************/
1352static bool load_game_names(struct section_file *file,
1353 struct rscompat_info *compat)
1354{
1355 struct section_list *sec;
1356 int nval;
1357 const char *filename = secfile_name(file);
1358 bool ok = TRUE;
1359
1360 /* section: datafile */
1362 if (compat->version <= 0) {
1363 return FALSE;
1364 }
1365
1366 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1367 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1368
1370 nval = (NULL != sec ? section_list_size(sec) : 0);
1372 int num = nval; /* No "size_t" to printf */
1373
1375 "\"%s\": Too many achievement types (%d, max %d)",
1376 filename, num, MAX_ACHIEVEMENT_TYPES);
1377 ok = FALSE;
1378 } else {
1380 }
1381
1382 if (ok) {
1385
1386 if (!ruleset_load_names(&pach->name, NULL, file, sec_name)) {
1388 "\"%s\": Cannot load achievement names",
1389 filename);
1390 ok = FALSE;
1391 break;
1392 }
1394 }
1395
1397
1398 if (ok) {
1400
1401 nval = (NULL != sec ? section_list_size(sec) : 0);
1402 if (nval > MAX_GOODS_TYPES) {
1403 int num = nval; /* No "size_t" to printf */
1404
1406 "\"%s\": Too many goods types (%d, max %d)",
1407 filename, num, MAX_GOODS_TYPES);
1409 ok = FALSE;
1410 } else if (nval < 1) {
1412 "\"%s\": At least one goods type needed",
1413 filename);
1415 ok = FALSE;
1416 } else {
1418 }
1419
1420 if (ok) {
1422 const char *sec_name
1424
1425 if (!ruleset_load_names(&pgood->name, NULL, file, sec_name)) {
1427 "\"%s\": Cannot load goods names",
1428 filename);
1429 ok = FALSE;
1430 break;
1431 }
1433 }
1435 }
1436
1437 if (ok) {
1438
1440
1441 nval = (NULL != sec ? section_list_size(sec) : 0);
1442 if (nval > MAX_COUNTERS) {
1443 size_t num = nval;
1444
1446 "\"%s\": Too many counters (" SIZE_T_PRINTF ", max %d)",
1447 filename, num, MAX_COUNTERS);
1448 ok = FALSE;
1449 }
1450
1451 if (ok) {
1452 int count_idx;
1453
1455
1456 for (count_idx = 0; count_idx < nval; count_idx++) {
1457
1459 const char *sec_name
1461
1462 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
1464 "\"%s\": Cannot load counters names",
1465 filename);
1466 ok = FALSE;
1467 break;
1468 }
1469 }
1470 }
1471
1473 }
1474
1475 return ok;
1476}
1477
1478/**********************************************************************/
1482static bool load_action_names(struct section_file *file,
1483 struct rscompat_info *compat)
1484{
1485 const char *filename = secfile_name(file);
1486 bool ok = TRUE;
1487
1488 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1489 return FALSE;
1490 }
1491
1492 (void) secfile_entry_by_path(file, "datafile.description"); /* Unused */
1493 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* Unused */
1494
1495 return ok;
1496}
1497
1498/**********************************************************************/
1502static bool load_tech_names(struct section_file *file,
1503 struct rscompat_info *compat)
1504{
1505 struct section_list *sec = NULL;
1506 /* Number of techs in the ruleset (means without A_NONE). */
1507 int num_techs = 0;
1508 int i;
1509 const char *filename = secfile_name(file);
1510 bool ok = TRUE;
1511 const char *flag;
1512
1513 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1514 return FALSE;
1515 }
1516
1517 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1518 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1519
1520 /* User tech flag names */
1521 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1522 i++) {
1523 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1524 i);
1527 "\"%s\": Duplicate tech flag name '%s'",
1528 filename, flag);
1529 ok = FALSE;
1530 break;
1531 }
1532 if (i > MAX_NUM_USER_TECH_FLAGS) {
1534 "\"%s\": Too many user tech flags!",
1535 filename);
1536 ok = FALSE;
1537 break;
1538 }
1539
1540 set_user_tech_flag_name(TECH_USER_1 + i, flag, helptxt);
1541 }
1542
1543 if (ok) {
1544 size_t nval;
1545
1546 for (; i < MAX_NUM_USER_TECH_FLAGS; i++) {
1548 }
1549
1550 /* Tech classes */
1552
1553 nval = (NULL != sec ? section_list_size(sec) : 0);
1554 if (nval > MAX_NUM_TECH_CLASSES) {
1555 int num = nval; /* No "size_t" to printf */
1556
1558 "\"%s\": Too many tech classes (%d, max %d)",
1559 filename, num, MAX_NUM_TECH_CLASSES);
1561 ok = FALSE;
1562 } else {
1564 }
1565
1566 if (ok) {
1568 const char *sec_name
1570
1571 if (!ruleset_load_names(&ptclass->name, NULL, file, sec_name)) {
1572 ruleset_error(NULL, LOG_ERROR, "\"%s\": Cannot load tech class names",
1573 filename);
1574 ok = FALSE;
1575 break;
1576 }
1578 }
1579 }
1580
1581 if (ok) {
1582 /* The techs: */
1584 if (NULL == sec || 0 == (num_techs = section_list_size(sec))) {
1586 "\"%s\": No Advances?!?", filename);
1587 ok = FALSE;
1588 } else {
1589 log_verbose("%d advances (including possibly unused)", num_techs);
1590 if (num_techs + A_FIRST > A_LAST) {
1592 "\"%s\": Too many advances (%d, max %d)",
1593 filename, num_techs, A_LAST - A_FIRST);
1594 ok = FALSE;
1595 }
1596 }
1597 }
1598
1599 if (ok) {
1600 game.control.num_tech_types = num_techs + A_FIRST; /* includes A_NONE */
1601
1602 i = 0;
1603 advance_iterate(adv) {
1604 if (!ruleset_load_names(&adv->name, NULL, file,
1606 ok = FALSE;
1607 break;
1608 }
1609 i++;
1611 }
1613
1614 return ok;
1615}
1616
1617/**********************************************************************/
1620static bool load_ruleset_techs(struct section_file *file,
1621 struct rscompat_info *compat)
1622{
1623 struct section_list *sec;
1624 const char **slist;
1625 int i;
1626 size_t nval;
1628 const char *filename = secfile_name(file);
1629 bool ok = TRUE;
1630
1632
1633 i = 0;
1635 const char *sec_name = section_name(section_list_get(sec, i));
1636
1637 ptclass->cost_pct = secfile_lookup_int_default(file, 100, "%s.%s",
1638 sec_name, "cost_pct");
1639
1640 i++;
1642
1644
1645 i = 0;
1646 advance_iterate(a) {
1647 const char *sec_name = section_name(section_list_get(sec, i));
1648 const char *sval;
1649 int j, ival;
1650 struct requirement_vector *research_reqs;
1651
1652 if (!lookup_tech(file, &a->require[AR_ONE], sec_name, "req1",
1653 filename, rule_name_get(&a->name))
1654 || !lookup_tech(file, &a->require[AR_TWO], sec_name, "req2",
1655 filename, rule_name_get(&a->name))
1656 || !lookup_tech(file, &a->require[AR_ROOT], sec_name, "root_req",
1657 filename, rule_name_get(&a->name))) {
1658 ok = FALSE;
1659 break;
1660 }
1661
1662 if ((A_NEVER == a->require[AR_ONE] && A_NEVER != a->require[AR_TWO])
1663 || (A_NEVER != a->require[AR_ONE] && A_NEVER == a->require[AR_TWO])) {
1665 "\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
1666 filename, sec_name, rule_name_get(&a->name));
1667 ok = FALSE;
1668 break;
1669 }
1670 if (a_none == a->require[AR_ONE] && a_none != a->require[AR_TWO]) {
1672 "\"%s\" [%s] \"%s\": should have \"None\" second.",
1673 filename, sec_name, rule_name_get(&a->name));
1674 ok = FALSE;
1675 break;
1676 }
1677
1678 if (game.control.num_tech_classes == 0) {
1679 a->tclass = NULL;
1680 } else {
1681 const char *classname;
1682
1683 classname = lookup_string(file, sec_name, "class");
1684 if (classname != NULL) {
1687 if (a->tclass == NULL) {
1689 "\"%s\" [%s] \"%s\": Unknown tech class \"%s\".",
1690 filename, sec_name, rule_name_get(&a->name), classname);
1691 ok = FALSE;
1692 break;
1693 }
1694 } else {
1695 a->tclass = NULL; /* Default */
1696 }
1697 }
1698
1699 research_reqs = lookup_req_list(file, compat, sec_name, "research_reqs",
1700 rule_name_get(&a->name));
1701 if (research_reqs == NULL) {
1702 ok = FALSE;
1703 break;
1704 }
1705
1706 requirement_vector_copy(&a->research_reqs, research_reqs);
1707
1708 BV_CLR_ALL(a->flags);
1709
1710 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
1711 for (j = 0; j < nval; j++) {
1712 sval = slist[j];
1713 if (strcmp(sval, "") == 0) {
1714 continue;
1715 }
1719 "\"%s\" [%s] \"%s\": bad flag name \"%s\".",
1720 filename, sec_name, rule_name_get(&a->name), sval);
1721 ok = FALSE;
1722 break;
1723 } else {
1724 BV_SET(a->flags, ival);
1725 }
1726 }
1727 free(slist);
1728
1729 if (!ok) {
1730 break;
1731 }
1732
1733 sz_strlcpy(a->graphic_str,
1734 secfile_lookup_str_default(file, "-", "%s.graphic", sec_name));
1735 sz_strlcpy(a->graphic_alt,
1737 "%s.graphic_alt", sec_name));
1738
1739 a->helptext = lookup_strvec(file, sec_name, "helptext");
1740 a->bonus_message = lookup_string(file, sec_name, "bonus_message");
1741 a->cost = secfile_lookup_int_default(file, -1, "%s.%s",
1742 sec_name, "cost");
1743 a->num_reqs = 0;
1744
1745 i++;
1747
1748 /* Propagate a root tech up into the tech tree. If a technology
1749 * X has Y has a root tech, then any technology requiring X (in the
1750 * normal way or as a root tech) also has Y as a root tech.
1751 * Later techs may gain a whole set of root techs in this way. The one
1752 * we store in AR_ROOT is a more or less arbitrary one of these,
1753 * also signalling that the set is non-empty; after this, you'll still
1754 * have to walk the tech tree to find them all. */
1755restart:
1756
1757 if (ok) {
1758 advance_iterate(a) {
1759 if (valid_advance(a)
1760 && A_NEVER != a->require[AR_ROOT]) {
1761 bool out_of_order = FALSE;
1762
1763 /* Now find any tech depending on this technology and update its
1764 * root_req. */
1765 advance_iterate(b) {
1766 if (valid_advance(b)
1767 && A_NEVER == b->require[AR_ROOT]
1768 && (a == b->require[AR_ONE] || a == b->require[AR_TWO])) {
1769 b->require[AR_ROOT] = a->require[AR_ROOT];
1770 b->inherited_root_req = TRUE;
1771 if (b < a) {
1773 }
1774 }
1776
1777 if (out_of_order) {
1778 /* HACK: If we just changed the root_tech of a lower-numbered
1779 * technology, we need to go back so that we can propagate the
1780 * root_tech up to that technology's parents... */
1781 goto restart;
1782 }
1783 }
1785
1786 /* Now rename A_NEVER to A_NONE for consistency */
1788 if (A_NEVER == a->require[AR_ROOT]) {
1789 a->require[AR_ROOT] = a_none;
1790 }
1792
1793 /* Some more consistency checking:
1794 Non-removed techs depending on removed techs is too
1795 broken to fix by default, so die.
1796 */
1797 advance_iterate(a) {
1798 if (valid_advance(a)) {
1799 /* We check for recursive tech loops later,
1800 * in build_required_techs_helper. */
1801 if (!valid_advance(a->require[AR_ONE])) {
1803 "\"%s\" tech \"%s\": req1 leads to removed tech.",
1804 filename, advance_rule_name(a));
1805 ok = FALSE;
1806 break;
1807 }
1808 if (!valid_advance(a->require[AR_TWO])) {
1810 "\"%s\" tech \"%s\": req2 leads to removed tech.",
1811 filename, advance_rule_name(a));
1812 ok = FALSE;
1813 break;
1814 }
1815 }
1817 }
1818
1820 if (ok) {
1822 }
1823
1824 return ok;
1825}
1826
1827/**********************************************************************/
1831static bool load_unit_names(struct section_file *file,
1832 struct rscompat_info *compat)
1833{
1834 struct section_list *sec = NULL;
1835 int nval = 0;
1836 int i;
1837 const char *filename = secfile_name(file);
1838 const char *flag;
1839 bool ok = TRUE;
1840
1841 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1842 return FALSE;
1843 }
1844
1845 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1846 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1847
1848 /* User unit flag names */
1849 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1850 i++) {
1851 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1852 i);
1853
1857 "\"%s\": Duplicate unit flag name '%s'",
1858 filename, flag);
1859 ok = FALSE;
1860 break;
1861 }
1862 if (i > MAX_NUM_USER_UNIT_FLAGS) {
1864 "\"%s\": Too many user unit type flags!",
1865 filename);
1866 ok = FALSE;
1867 break;
1868 }
1869
1871 }
1872
1873 if (ok) {
1874 /* Blank the remaining unit type user flags. */
1875 for (; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
1877 }
1878 }
1879
1880 if (ok) {
1881 /* User unit class flag names */
1882 for (i = 0;
1883 (flag = secfile_lookup_str_default(file, NULL,
1884 "control.class_flags%d.name",
1885 i));
1886 i++) {
1887 const char *helptxt = secfile_lookup_str_default(file, NULL,
1888 "control.class_flags%d.helptxt", i);
1889
1893 "\"%s\": Duplicate unit class flag name '%s'",
1894 filename, flag);
1895 ok = FALSE;
1896 break;
1897 }
1900 "\"%s\": Too many user unit class flags!",
1901 filename);
1902 ok = FALSE;
1903 break;
1904 }
1905
1907 }
1908 }
1909
1910 if (ok) {
1911 /* Blank the remaining unit class user flags. */
1912 for (; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
1914 }
1915 }
1916
1917 if (ok) {
1918 /* Unit classes */
1920 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1922 "\"%s\": No unit classes?!?", filename);
1923 ok = FALSE;
1924 } else {
1925 log_verbose("%d unit classes", nval);
1926 if (nval > UCL_LAST) {
1928 "\"%s\": Too many unit classes (%d, max %d)",
1929 filename, nval, UCL_LAST);
1930 ok = FALSE;
1931 }
1932 }
1933 }
1934
1935 if (ok) {
1937
1939 const int pci = uclass_index(punitclass);
1940
1941 if (!ruleset_load_names(&punitclass->name, NULL, file,
1943 ok = FALSE;
1944 break;
1945 }
1947 }
1949 sec = NULL;
1950
1951 /* The names: */
1952 if (ok) {
1954 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1956 "\"%s\": No unit types?!?", filename);
1957 ok = FALSE;
1958 } else {
1959 log_verbose("%d unit types (including possibly unused)", nval);
1960 if (nval > U_LAST) {
1962 "\"%s\": Too many unit types (%d, max %d)",
1963 filename, nval, U_LAST);
1964 ok = FALSE;
1965 }
1966 }
1967 }
1968
1969 if (ok) {
1971
1973 const int utypei = utype_index(punittype);
1974 if (!ruleset_load_names(&punittype->name, NULL, file,
1976 ok = FALSE;
1977 break;
1978 }
1980 }
1982
1983 return ok;
1984}
1985
1986/**********************************************************************/
1989static bool load_ruleset_veteran(struct section_file *file,
1990 const char *path,
1991 struct veteran_system **vsystem, char *err,
1992 size_t err_len)
1993{
1994 const char **vlist_name;
1997 int i;
1998 bool ret = TRUE;
1999
2000 /* The pointer should be uninitialised. */
2001 if (*vsystem != NULL) {
2002 fc_snprintf(err, err_len, "Veteran system is defined?!");
2003 return FALSE;
2004 }
2005
2006 /* Load data. */
2008 "%s.veteran_names", path);
2010 "%s.veteran_power_fact", path);
2012 "%s.veteran_base_raise_chance", path);
2014 "%s.veteran_work_raise_chance",
2015 path);
2017 "%s.veteran_move_bonus", path);
2018
2019 if (count_name > MAX_VET_LEVELS) {
2020 ret = FALSE;
2021 fc_snprintf(err, err_len, "\"%s\": Too many veteran levels (section "
2022 "'%s': %lu, max %d)", secfile_name(file), path,
2023 (long unsigned)count_name, MAX_VET_LEVELS);
2024 } else if (count_name != count_power
2027 || count_name != count_move) {
2028 ret = FALSE;
2029 fc_snprintf(err, err_len, "\"%s\": Different lengths for the veteran "
2030 "settings in section '%s'", secfile_name(file),
2031 path);
2032 } else if (count_name == 0) {
2033 /* Nothing defined. */
2034 *vsystem = NULL;
2035 } else {
2036 /* Generate the veteran system. */
2038
2039#define rs_sanity_veteran(_path, _entry, _i, _condition, _action) \
2040 if (_condition) { \
2041 log_error("Invalid veteran definition '%s.%s[%d]'!", \
2042 _path, _entry, _i); \
2043 log_debug("Failed check: '%s'. Update value: '%s'.", \
2044 #_condition, #_action); \
2045 _action; \
2046 }
2047 for (i = 0; i < count_name; i++) {
2048 /* Some sanity checks. */
2049 rs_sanity_veteran(path, "veteran_power_fact", i,
2050 (vlist_power[i] < 0), vlist_power[i] = 0);
2051 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2052 (vlist_raise[i] < 0), vlist_raise[i] = 0);
2053 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2054 (vlist_wraise[i] < 0), vlist_wraise[i] = 0);
2055 rs_sanity_veteran(path, "veteran_move_bonus", i,
2056 (vlist_move[i] < 0), vlist_move[i] = 0);
2057 if (i == 0) {
2058 /* First element.*/
2059 rs_sanity_veteran(path, "veteran_power_fact", i,
2060 (vlist_power[i] != 100), vlist_power[i] = 100);
2061 } else if (i == count_name - 1) {
2062 /* Last element. */
2063 rs_sanity_veteran(path, "veteran_power_fact", i,
2064 (vlist_power[i] < vlist_power[i - 1]),
2065 vlist_power[i] = vlist_power[i - 1]);
2066 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2067 (vlist_raise[i] != 0), vlist_raise[i] = 0);
2068 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2069 (vlist_wraise[i] != 0), vlist_wraise[i] = 0);
2070 } else {
2071 /* All elements in between. */
2072 rs_sanity_veteran(path, "veteran_power_fact", i,
2073 (vlist_power[i] < vlist_power[i - 1]),
2074 vlist_power[i] = vlist_power[i - 1]);
2075 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2076 (vlist_raise[i] > 100), vlist_raise[i] = 100);
2077 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2078 (vlist_wraise[i] > 100), vlist_wraise[i] = 100);
2079 }
2080
2083 vlist_wraise[i]);
2084 }
2085#undef rs_sanity_veteran
2086 }
2087
2088 if (vlist_name) {
2090 }
2091 if (vlist_power) {
2093 }
2094 if (vlist_raise) {
2096 }
2097 if (vlist_wraise) {
2099 }
2100 if (vlist_move) {
2102 }
2103
2104 return ret;
2105}
2106
2107/**********************************************************************/
2110static bool load_ruleset_units(struct section_file *file,
2111 struct rscompat_info *compat)
2112{
2113 int j, ival;
2114 size_t nval;
2115 struct section_list *sec, *csec;
2116 const char *sval, **slist;
2117 const char *filename = secfile_name(file);
2118 char msg[MAX_LEN_MSG];
2119 bool ok = TRUE;
2120
2121 if (!load_ruleset_veteran(file, "veteran_system", &game.veteran, msg,
2122 sizeof(msg))
2123 || game.veteran == NULL) {
2125 "Error loading the default veteran system: %s",
2126 msg);
2127 ok = FALSE;
2128 }
2129
2131 nval = (NULL != sec ? section_list_size(sec) : 0);
2132
2134 nval = (NULL != csec ? section_list_size(csec) : 0);
2135
2136 if (ok) {
2138 int i = uclass_index(uc);
2139 const char *sec_name = section_name(section_list_get(csec, i));
2140
2141 if (secfile_lookup_int(file, &uc->min_speed, "%s.min_speed", sec_name)) {
2142 uc->min_speed *= SINGLE_MOVE;
2143 } else {
2145 ok = FALSE;
2146 break;
2147 }
2148 if (!secfile_lookup_int(file, &uc->hp_loss_pct,
2149 "%s.hp_loss_pct", sec_name)) {
2151 ok = FALSE;
2152 break;
2153 }
2154
2155 uc->non_native_def_pct = secfile_lookup_int_default(file, 100,
2156 "%s.non_native_def_pct",
2157 sec_name);
2158
2159 BV_CLR_ALL(uc->flags);
2160 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
2161 for (j = 0; j < nval; j++) {
2162 sval = slist[j];
2163 if (strcmp(sval, "") == 0) {
2164 continue;
2165 }
2168 ok = FALSE;
2172 "\"%s\" unit_class \"%s\": unit_type flag \"%s\"!",
2173 filename, uclass_rule_name(uc), sval);
2174 } else {
2176 "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
2177 filename, uclass_rule_name(uc), sval);
2178 }
2179 break;
2180 } else {
2181 BV_SET(uc->flags, ival);
2182 }
2183 }
2184 free(slist);
2185
2186 uc->helptext = lookup_strvec(file, sec_name, "helptext");
2187
2188 if (!ok) {
2189 break;
2190 }
2192 }
2193
2194 if (ok) {
2195 /* Tech and Gov requirements; per unit veteran system */
2197 const int i = utype_index(u);
2198 const struct section *psection = section_list_get(sec, i);
2199 const char *sec_name = section_name(psection);
2200
2201 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
2202 struct advance *adv_req;
2203 struct impr_type *impr_req = NULL;
2204
2205 if (!lookup_tech(file, &adv_req, sec_name,
2206 "tech_req", filename,
2207 rule_name_get(&u->name))) {
2208 ok = FALSE;
2209 break;
2210 }
2211 if (adv_req == A_NEVER) {
2212 ruleset_error(NULL, LOG_ERROR, "%s lacks valid tech_req.",
2213 rule_name_get(&u->name));
2214 ok = FALSE;
2215 break;
2216 } else if (adv_req != advance_by_number(A_NONE)) {
2217 requirement_vector_append(&u->build_reqs,
2219 FALSE, TRUE, FALSE,
2221 }
2222
2223 /* Read the government build requirement from the old ruleset format
2224 * and put it in unit_type's build_reqs requirement vector.
2225 * The build_reqs requirement vector isn't ready to be exposed in the
2226 * ruleset yet.
2227 * Barbarians can build certain units as long as anyone in the world
2228 * has the required tech. Regular players must have the required tech
2229 * them self to build the same unit. One way to solve this is to make
2230 * unit building an action enabler controlled action with a city (not
2231 * unit) actor.
2232 * Putting a requirement vector on unit types in the ruleset will
2233 * force ruleset authors to change all their unit type build
2234 * requirements to a requirement vector. Forcing them to convert their
2235 * unit type requirements again in the next version (should building be
2236 * switched to an action enabler with a city actor) is not good. */
2237 if (NULL != section_entry_by_name(psection, "gov_req")) {
2238 char tmp[200] = "\0";
2240
2241 fc_strlcat(tmp, section_name(psection), sizeof(tmp));
2242 fc_strlcat(tmp, ".gov_req", sizeof(tmp));
2243 need_government = lookup_government(file, tmp, filename, NULL);
2244 if (need_government == NULL) {
2245 ok = FALSE;
2246 break;
2247 }
2250 FALSE, TRUE, FALSE,
2252 }
2253
2254 /* Read the building build requirement from the old ruleset format
2255 * and put it in unit_type's build_reqs requirement vector.
2256 * The build_reqs requirement vector isn't ready to be exposed in the
2257 * ruleset yet.
2258 * See the comment for gov_req above for why. */
2259 if (!lookup_building(file, sec_name, "impr_req",
2260 &impr_req, filename,
2261 rule_name_get(&u->name))) {
2262 ok = FALSE;
2263 break;
2264 }
2265 if (impr_req) {
2268 FALSE, TRUE, FALSE,
2270 }
2271 } else {
2272 /* Freeciv-3.2 format */
2273 struct requirement_vector *reqs;
2274
2275 reqs = lookup_req_list(file, compat, sec_name, "reqs",
2276 utype_rule_name(u));
2277
2278 if (reqs == NULL) {
2279 ok = FALSE;
2280 break;
2281 }
2282
2283 requirement_vector_copy(&u->build_reqs, reqs);
2284 }
2285
2286 if (!load_ruleset_veteran(file, sec_name, &u->veteran,
2287 msg, sizeof(msg))) {
2289 "Error loading the veteran system: %s",
2290 msg);
2291 ok = FALSE;
2292 break;
2293 }
2294
2295 if (!lookup_unit_type(file, sec_name, "obsolete_by",
2296 &u->obsoleted_by, filename,
2297 rule_name_get(&u->name))
2298 || !lookup_unit_type(file, sec_name, "convert_to",
2299 &u->converted_to, filename,
2300 rule_name_get(&u->name))) {
2301 ok = FALSE;
2302 break;
2303 }
2304 u->convert_time = 1; /* default */
2305 lookup_time(file, &u->convert_time, sec_name, "convert_time",
2306 filename, rule_name_get(&u->name), &ok);
2308 }
2309
2310 if (ok) {
2311 /* main stats: */
2313 const int i = utype_index(u);
2314 struct unit_class *pclass;
2315 const char *sec_name = section_name(section_list_get(sec, i));
2316 const char *str;
2317
2318 sval = secfile_lookup_str(file, "%s.class", sec_name);
2320 if (!pclass) {
2322 "\"%s\" unit_type \"%s\": bad class \"%s\".",
2323 filename, utype_rule_name(u), sval);
2324 ok = FALSE;
2325 break;
2326 }
2327 u->uclass = pclass;
2328
2329 sz_strlcpy(u->sound_move,
2330 secfile_lookup_str_default(file, "-", "%s.sound_move",
2331 sec_name));
2332 sz_strlcpy(u->sound_move_alt,
2333 secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
2334 sec_name));
2335 sz_strlcpy(u->sound_fight,
2336 secfile_lookup_str_default(file, "-", "%s.sound_fight",
2337 sec_name));
2338 sz_strlcpy(u->sound_fight_alt,
2339 secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
2340 sec_name));
2341
2342 if ((str = secfile_lookup_str(file, "%s.graphic", sec_name))) {
2343 sz_strlcpy(u->graphic_str, str);
2344 } else {
2346 ok = FALSE;
2347 break;
2348 }
2349 sz_strlcpy(u->graphic_alt,
2350 secfile_lookup_str_default(file, "-", "%s.graphic_alt",
2351 sec_name));
2352 sz_strlcpy(u->graphic_alt2,
2353 secfile_lookup_str_default(file, "-", "%s.graphic_alt2",
2354 sec_name));
2355
2356 if (!secfile_lookup_int(file, &u->build_cost,
2357 "%s.build_cost", sec_name)
2358 || !secfile_lookup_int(file, &u->pop_cost,
2359 "%s.pop_cost", sec_name)
2360 || !secfile_lookup_int(file, &u->attack_strength,
2361 "%s.attack", sec_name)
2362 || !secfile_lookup_int(file, &u->defense_strength,
2363 "%s.defense", sec_name)
2364 || !secfile_lookup_int(file, &u->move_rate,
2365 "%s.move_rate", sec_name)
2366 || !secfile_lookup_int(file, &u->vision_radius_sq,
2367 "%s.vision_radius_sq", sec_name)
2368 || !secfile_lookup_int(file, &u->transport_capacity,
2369 "%s.transport_cap", sec_name)
2370 || !secfile_lookup_int(file, &u->hp,
2371 "%s.hitpoints", sec_name)
2372 || !secfile_lookup_int(file, &u->firepower,
2373 "%s.firepower", sec_name)
2374 || !secfile_lookup_int(file, &u->fuel,
2375 "%s.fuel", sec_name)
2376 || !secfile_lookup_int(file, &u->happy_cost,
2377 "%s.uk_happy", sec_name)) {
2379 ok = FALSE;
2380 break;
2381 }
2382 u->move_rate *= SINGLE_MOVE;
2383
2384 if (u->firepower <= 0) {
2386 "\"%s\" unit_type \"%s\":"
2387 " firepower is %d,"
2388 " but must be at least 1. "
2389 " If you want no attack ability,"
2390 " set the unit's attack strength to 0.",
2391 filename, utype_rule_name(u), u->firepower);
2392 ok = FALSE;
2393 break;
2394 }
2395
2396 lookup_cbonus_list(u->bonuses, file, sec_name, "bonuses");
2397
2399 u->upkeep[o] = secfile_lookup_int_default(file, 0, "%s.uk_%s",
2400 sec_name,
2403
2404 slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec_name);
2405
2406 BV_CLR_ALL(u->cargo);
2407 for (j = 0; j < nval; j++) {
2408 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2409
2410 if (!uclass) {
2412 "\"%s\" unit_type \"%s\":"
2413 "has unknown unit class %s as cargo.",
2414 filename, utype_rule_name(u), slist[j]);
2415 ok = FALSE;
2416 break;
2417 }
2418
2419 BV_SET(u->cargo, uclass_index(uclass));
2420 }
2421 free(slist);
2422
2423 if (!ok) {
2424 break;
2425 }
2426
2427 slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec_name);
2428 BV_CLR_ALL(u->targets);
2429 for (j = 0; j < nval; j++) {
2430 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2431
2432 if (!uclass) {
2434 "\"%s\" unit_type \"%s\":"
2435 "has unknown unit class %s as target.",
2436 filename, utype_rule_name(u), slist[j]);
2437 ok = FALSE;
2438 break;
2439 }
2440
2441 BV_SET(u->targets, uclass_index(uclass));
2442 }
2443 free(slist);
2444
2445 if (!ok) {
2446 break;
2447 }
2448
2449 slist = secfile_lookup_str_vec(file, &nval, "%s.embarks", sec_name);
2450 BV_CLR_ALL(u->embarks);
2451 for (j = 0; j < nval; j++) {
2452 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2453
2454 if (!uclass) {
2456 "\"%s\" unit_type \"%s\":"
2457 "has unknown unit class %s as embarkable.",
2458 filename, utype_rule_name(u), slist[j]);
2459 ok = FALSE;
2460 break;
2461 }
2462
2463 BV_SET(u->embarks, uclass_index(uclass));
2464 }
2465 free(slist);
2466
2467 if (!ok) {
2468 break;
2469 }
2470
2471 slist = secfile_lookup_str_vec(file, &nval, "%s.disembarks", sec_name);
2472 BV_CLR_ALL(u->disembarks);
2473 for (j = 0; j < nval; j++) {
2474 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2475
2476 if (!uclass) {
2478 "\"%s\" unit_type \"%s\":"
2479 "has unknown unit class %s as disembarkable.",
2480 filename, utype_rule_name(u), slist[j]);
2481 ok = FALSE;
2482 break;
2483 }
2484
2485 BV_SET(u->disembarks, uclass_index(uclass));
2486 }
2487 free(slist);
2488
2489 if (!ok) {
2490 break;
2491 }
2492
2493 /* Set also all classes that are never unreachable as targets,
2494 * embarks, and disembarks. */
2497 BV_SET(u->targets, uclass_index(preachable));
2498 BV_SET(u->embarks, uclass_index(preachable));
2499 BV_SET(u->disembarks, uclass_index(preachable));
2500 }
2502
2503 str = secfile_lookup_str_default(file, "Main", "%s.vision_layer",
2504 sec_name);
2506 if (!vision_layer_is_valid(u->vlayer)) {
2508 "\"%s\" unit_type \"%s\":"
2509 "has unknown vision layer %s.",
2510 filename, utype_rule_name(u), str);
2511 ok = FALSE;
2512 break;
2513 }
2514
2515 u->helptext = lookup_strvec(file, sec_name, "helptext");
2516
2517 u->paratroopers_range = secfile_lookup_int_default(file,
2518 0, "%s.paratroopers_range", sec_name);
2519
2520 u->bombard_rate = secfile_lookup_int_default(file, 0,
2521 "%s.bombard_rate", sec_name);
2522 u->city_slots = secfile_lookup_int_default(file, 0,
2523 "%s.city_slots", sec_name);
2524 u->city_size = secfile_lookup_int_default(file, 1,
2525 "%s.city_size", sec_name);
2526
2528 "%s.tp_defense", sec_name);
2529 u->tp_defense = transp_def_type_by_name(sval, fc_strcasecmp);
2530 if (!transp_def_type_is_valid(u->tp_defense)) {
2532 "\"%s\" unit_type \"%s\":"
2533 " bad tp_defense \"%s\".",
2534 filename, utype_rule_name(u), sval);
2535 ok = FALSE;
2536 break;
2537 }
2539 }
2540
2541 if (ok) {
2542 /* flags */
2544 const int i = utype_index(u);
2545
2546 BV_CLR_ALL(u->flags);
2548
2549 slist = secfile_lookup_str_vec(file, &nval, "%s.flags",
2551 for (j = 0; j < nval; j++) {
2552 sval = slist[j];
2553 if (0 == strcmp(sval, "")) {
2554 continue;
2555 }
2558 ok = FALSE;
2562 "\"%s\" unit_type \"%s\": unit_class flag!",
2563 filename, utype_rule_name(u));
2564 } else {
2566 "\"%s\" unit_type \"%s\": bad flag name \"%s\".",
2567 filename, utype_rule_name(u), sval);
2568 }
2569 break;
2570 } else {
2571 BV_SET(u->flags, ival);
2572 }
2573 }
2574 free(slist);
2575
2576 if (!ok) {
2577 break;
2578 }
2580 }
2581
2582 /* roles */
2583 if (ok) {
2585 const int i = utype_index(u);
2586
2587 BV_CLR_ALL(u->roles);
2588
2589 slist = secfile_lookup_str_vec(file, &nval, "%s.roles",
2591 for (j = 0; j < nval; j++) {
2592 sval = slist[j];
2593 if (strcmp(sval, "") == 0) {
2594 continue;
2595 }
2599 "\"%s\" unit_type \"%s\": bad role name \"%s\".",
2600 filename, utype_rule_name(u), sval);
2601 ok = FALSE;
2602 break;
2603 } else {
2604 BV_SET(u->roles, ival - L_FIRST);
2605 }
2607 }
2608 free(slist);
2610 }
2611
2612 if (ok) {
2613 /* Some more consistency checking: */
2616 if (!valid_advance(padv)) {
2618 "\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
2619 filename, utype_rule_name(u),
2621 ok = FALSE;
2622 break;
2623 }
2625
2626 if (!ok) {
2627 break;
2628 }
2630 }
2631
2634
2635 if (ok) {
2637 }
2638
2639 return ok;
2640}
2641
2642/**********************************************************************/
2646static bool load_building_names(struct section_file *file,
2647 struct rscompat_info *compat)
2648{
2649 struct section_list *sec;
2650 int i, nval = 0;
2651 const char *filename = secfile_name(file);
2652 bool ok = TRUE;
2653 const char *flag;
2654
2655 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2656 return FALSE;
2657 }
2658
2659 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2660 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2661
2662 /* The names: */
2664 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2666 "\"%s\": No improvements?!?", filename);
2667 ok = FALSE;
2668 } else {
2669 log_verbose("%d improvement types (including possibly unused)", nval);
2670 if (nval > B_LAST) {
2672 "\"%s\": Too many improvements (%d, max %d)",
2673 filename, nval, B_LAST);
2674 ok = FALSE;
2675 }
2676 }
2677
2678 if (ok) {
2680
2681 for (i = 0; i < nval; i++) {
2682 struct impr_type *b = improvement_by_number(i);
2683
2684 if (!ruleset_load_names(&b->name, NULL, file, section_name(section_list_get(sec, i)))) {
2685 ok = FALSE;
2686 break;
2687 }
2688 }
2689 }
2690
2691 /* User building flag names */
2692 for (i = 0;
2693 (flag = secfile_lookup_str_default(file, NULL,
2694 "control.building_flags%d.name",
2695 i));
2696 i++) {
2697 const char *helptxt = secfile_lookup_str_default(file, NULL,
2698 "control.building_flags%d.helptxt", i);
2699
2701 != impr_flag_id_invalid()) {
2703 "\"%s\": Duplicate building flag name '%s'",
2704 filename, flag);
2705 ok = FALSE;
2706 break;
2707 }
2710 "\"%s\": Too many user building flags!",
2711 filename);
2712 ok = FALSE;
2713 break;
2714 }
2715
2716 set_user_impr_flag_name(IF_USER_FLAG_1 + i, flag, helptxt);
2717 }
2718
2720
2721 return ok;
2722}
2723
2724/**********************************************************************/
2727static bool load_ruleset_buildings(struct section_file *file,
2728 struct rscompat_info *compat)
2729{
2730 struct section_list *sec;
2731 const char *item;
2732 int i, nval;
2733 const char *filename = secfile_name(file);
2734 bool ok = TRUE;
2735
2737 nval = (NULL != sec ? section_list_size(sec) : 0);
2738
2739 for (i = 0; i < nval && ok; i++) {
2740 struct impr_type *b = improvement_by_number(i);
2741 const char *sec_name = section_name(section_list_get(sec, i));
2742 struct requirement_vector *reqs =
2743 lookup_req_list(file, compat, sec_name, "reqs",
2745
2746 if (reqs == NULL) {
2747 ok = FALSE;
2748 break;
2749 } else {
2750 const char *sval, **slist;
2751 int j, ival;
2752 size_t nflags;
2753
2754 item = secfile_lookup_str(file, "%s.genus", sec_name);
2756 if (!impr_genus_id_is_valid(b->genus)) {
2758 "\"%s\" improvement \"%s\": couldn't match "
2759 "genus \"%s\".", filename,
2761 ok = FALSE;
2762 break;
2763 }
2764
2765 slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec_name);
2766 BV_CLR_ALL(b->flags);
2767
2768 for (j = 0; j < nflags; j++) {
2769 sval = slist[j];
2770 if (strcmp(sval, "") == 0) {
2771 continue;
2772 }
2776 "\"%s\" improvement \"%s\": bad flag name \"%s\".",
2777 filename, improvement_rule_name(b), sval);
2778 ok = FALSE;
2779 break;
2780 } else {
2781 BV_SET(b->flags, ival);
2782 }
2783 }
2784 free(slist);
2785
2786 if (!ok) {
2787 break;
2788 }
2789
2790 if (compat->compat_mode) {
2792 }
2793
2795
2796 {
2797 struct requirement_vector *obs_reqs =
2798 lookup_req_list(file, compat, sec_name, "obsolete_by",
2800
2801 if (obs_reqs == NULL) {
2802 ok = FALSE;
2803 break;
2804 } else {
2805 requirement_vector_copy(&b->obsolete_by, obs_reqs);
2806 }
2807 }
2808
2809 if (!secfile_lookup_int(file, &b->build_cost,
2810 "%s.build_cost", sec_name)
2811 || !secfile_lookup_int(file, &b->upkeep,
2812 "%s.upkeep", sec_name)
2813 || !secfile_lookup_int(file, &b->sabotage,
2814 "%s.sabotage", sec_name)) {
2816 ok = FALSE;
2817 break;
2818 }
2819
2822 "%s.graphic", sec_name));
2825 "%s.graphic_alt", sec_name));
2828 "%s.graphic_alt2", sec_name));
2829
2832 "%s.sound", sec_name));
2835 "%s.sound_alt", sec_name));
2838 "%s.sound_alt2", sec_name));
2839 b->helptext = lookup_strvec(file, sec_name, "helptext");
2840 }
2841 }
2842
2844 if (ok) {
2846 }
2847
2848 return ok;
2849}
2850
2851/**********************************************************************/
2855static bool load_terrain_names(struct section_file *file,
2856 struct rscompat_info *compat)
2857{
2858 int nval = 0;
2859 struct section_list *sec = NULL;
2860 const char *flag;
2861 int i;
2862 const char *filename = secfile_name(file);
2863 bool ok = TRUE;
2864
2865 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2866 return FALSE;
2867 }
2868
2869 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2870 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2871
2872 /* User terrain flag names */
2873 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
2874 i++) {
2875 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
2876 i);
2877
2881 "\"%s\": Duplicate terrain flag name '%s'",
2882 filename, flag);
2883 ok = FALSE;
2884 break;
2885 }
2886 if (i > MAX_NUM_USER_TER_FLAGS) {
2888 "\"%s\": Too many user terrain flags!",
2889 filename);
2890 ok = FALSE;
2891 break;
2892 }
2893
2894 set_user_terrain_flag_name(TER_USER_1 + i, flag, helptxt);
2895 }
2896
2897 if (ok) {
2898 /* Blank the remaining terrain user flag slots. */
2899 for (; i < MAX_NUM_USER_TER_FLAGS; i++) {
2901 }
2902 }
2903
2904 /* User extra flag names */
2905 for (i = 0;
2906 (flag = secfile_lookup_str_default(file, NULL,
2907 "control.extra_flags%d.name",
2908 i));
2909 i++) {
2910 const char *helptxt = secfile_lookup_str_default(file, NULL,
2911 "control.extra_flags%d.helptxt", i);
2912
2914 != extra_flag_id_invalid()) {
2916 "\"%s\": Duplicate extra flag name '%s'",
2917 filename, flag);
2918 ok = FALSE;
2919 break;
2920 }
2923 "\"%s\": Too many user extra flags!",
2924 filename);
2925 ok = FALSE;
2926 break;
2927 }
2928
2929 set_user_extra_flag_name(EF_USER_FLAG_1 + i, flag, helptxt);
2930 }
2931
2932 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
2934 }
2935
2936 if (ok) {
2937 /* Blank the remaining extra user flag slots. */
2938 for (; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
2940 }
2941
2942 /* terrain names */
2943
2945 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2947 "\"%s\": ruleset doesn't have any terrains.",
2948 filename);
2949 ok = FALSE;
2950 } else {
2951 if (nval > MAX_NUM_TERRAINS) {
2953 "\"%s\": Too many terrains (%d, max %d)",
2954 filename, nval, MAX_NUM_TERRAINS);
2955 ok = FALSE;
2956 }
2957 }
2958 }
2959
2960 if (ok) {
2962
2963 /* avoid re-reading files */
2964 if (terrain_sections) {
2966 }
2968
2969 terrain_type_iterate(pterrain) {
2970 const int terri = terrain_index(pterrain);
2971 const char *sec_name = section_name(section_list_get(sec, terri));
2972
2973 if (!ruleset_load_names(&pterrain->name, NULL, file, sec_name)) {
2974 ok = FALSE;
2975 break;
2976 }
2977
2980 }
2981
2983 sec = NULL;
2984
2985 /* extra names */
2986
2987 if (ok) {
2989 nval = (NULL != sec ? section_list_size(sec) : 0);
2990 if (nval > MAX_EXTRA_TYPES) {
2992 "\"%s\": Too many extra types (%d, max %d)",
2993 filename, nval, MAX_EXTRA_TYPES);
2994 ok = FALSE;
2995 }
2996 }
2997
2998 if (ok) {
2999 int idx;
3000
3002
3003 if (extra_sections) {
3005 }
3007
3008 if (ok) {
3009 for (idx = 0; idx < nval; idx++) {
3010 const char *sec_name = section_name(section_list_get(sec, idx));
3011 struct extra_type *pextra = extra_by_number(idx);
3012
3013 if (!ruleset_load_names(&pextra->name, NULL, file, sec_name)) {
3014 ok = FALSE;
3015 break;
3016 }
3018 }
3019 }
3020 }
3021
3023 sec = NULL;
3024
3025 /* Base names */
3026
3027 if (ok) {
3029 nval = (NULL != sec ? section_list_size(sec) : 0);
3030 if (nval > MAX_EXTRA_TYPES) {
3032 "\"%s\": Too many base types (%d, max %d)",
3033 filename, nval, MAX_EXTRA_TYPES);
3034 ok = FALSE;
3035 }
3036
3038 }
3039
3040 if (ok) {
3041 int idx;
3042
3043 if (base_sections) {
3045 }
3047
3048 /* Cannot use base_type_iterate() before bases are added to
3049 * EC_BASE caused_by list. Have to get them by extra_type_by_rule_name() */
3050 for (idx = 0; idx < nval; idx++) {
3051 const char *sec_name = section_name(section_list_get(sec, idx));
3052 const char *base_name = secfile_lookup_str(file, "%s.extra", sec_name);
3053
3054 if (base_name != NULL) {
3056
3057 if (pextra != NULL) {
3058 base_type_init(pextra, idx);
3060 } else {
3062 "No extra definition matching base definition \"%s\"",
3063 base_name);
3064 ok = FALSE;
3065 }
3066 } else {
3068 "Base section \"%s\" does not associate base with any extra",
3069 sec_name);
3070 ok = FALSE;
3071 }
3072 }
3073 }
3074
3076 sec = NULL;
3077
3078 /* Road names */
3079
3080 if (ok) {
3082 nval = (NULL != sec ? section_list_size(sec) : 0);
3083 if (nval > MAX_EXTRA_TYPES) {
3085 "\"%s\": Too many road types (%d, max %d)",
3086 filename, nval, MAX_EXTRA_TYPES);
3087 ok = FALSE;
3088 }
3089
3091 }
3092
3093 if (ok) {
3094 int idx;
3095
3096 if (road_sections) {
3098 }
3100
3101 /* Cannot use extra_type_by_cause_iterate(EC_ROAD) before roads are added to
3102 * EC_ROAD caused_by list. Have to get them by extra_type_by_rule_name() */
3103 for (idx = 0; idx < nval; idx++) {
3104 const char *sec_name = section_name(section_list_get(sec, idx));
3105 const char *road_name = secfile_lookup_str(file, "%s.extra", sec_name);
3106
3107 if (road_name != NULL) {
3109
3110 if (pextra != NULL) {
3111 road_type_init(pextra, idx);
3113 } else {
3115 "No extra definition matching road definition \"%s\"",
3116 road_name);
3117 ok = FALSE;
3118 }
3119 } else {
3121 "Road section \"%s\" does not associate road with any extra",
3122 sec_name);
3123 ok = FALSE;
3124 }
3125 }
3126 }
3127
3129 sec = NULL;
3130
3131 /* Resource names */
3132 if (ok) {
3134 nval = (NULL != sec ? section_list_size(sec) : 0);
3135 if (nval > MAX_EXTRA_TYPES) {
3137 "\"%s\": Too many resource types (%d, max %d)",
3138 filename, nval, MAX_EXTRA_TYPES);
3139 ok = FALSE;
3140 }
3141
3143 }
3144
3145 if (ok) {
3146 int idx;
3147
3148 if (resource_sections) {
3150 }
3152
3153 /* Cannot use resource_type_iterate() before resource are added to
3154 * EC_RESOURCE caused_by list. Have to get them by extra_type_by_rule_name() */
3155 for (idx = 0; idx < nval; idx++) {
3156 const char *sec_name = section_name(section_list_get(sec, idx));
3157 const char *resource_name;
3158 struct extra_type *pextra = NULL;
3159
3161
3162 if (resource_name != NULL) {
3164
3165 if (pextra != NULL) {
3166 resource_type_init(pextra);
3168 } else {
3170 "No extra definition matching resource definition \"%s\"",
3172 ok = FALSE;
3173 }
3174 } else {
3176 "Resource section %s does not list extra this resource belongs to.",
3177 sec_name);
3178 ok = FALSE;
3179 }
3180 }
3181 }
3182
3184
3185 return ok;
3186}
3187
3188/**********************************************************************/
3191static bool load_ruleset_terrain(struct section_file *file,
3192 struct rscompat_info *compat)
3193{
3194 size_t nval, nval2;
3195 int j;
3196 bool compat_road = FALSE;
3197 bool compat_rail = FALSE;
3198 bool compat_river = FALSE;
3199 const char **res;
3200 const char *filename = secfile_name(file);
3201 const char *text;
3202 int *res_freq;
3203 bool ok = TRUE;
3204
3205 /* parameters */
3206
3207 terrain_control.ocean_reclaim_requirement_pct
3208 = secfile_lookup_int_default(file, 101,
3209 "parameters.ocean_reclaim_requirement");
3210 terrain_control.land_channel_requirement_pct
3211 = secfile_lookup_int_default(file, 101,
3212 "parameters.land_channel_requirement");
3213 terrain_control.terrain_thaw_requirement_pct
3214 = secfile_lookup_int_default(file, 101,
3215 "parameters.thaw_requirement");
3216 terrain_control.terrain_freeze_requirement_pct
3217 = secfile_lookup_int_default(file, 101,
3218 "parameters.freeze_requirement");
3219 terrain_control.lake_max_size
3221 "parameters.lake_max_size");
3222 terrain_control.min_start_native_area
3224 "parameters.min_start_native_area");
3225 terrain_control.move_fragments
3227 "parameters.move_fragments");
3228 if (terrain_control.move_fragments < 1) {
3230 "\"%s\": move_fragments must be at least 1",
3231 filename);
3232 ok = FALSE;
3233 }
3235 terrain_control.igter_cost
3237 "parameters.igter_cost");
3238 if (terrain_control.igter_cost < 1) {
3240 "\"%s\": igter_cost must be at least 1",
3241 filename);
3242 ok = FALSE;
3243 }
3244 terrain_control.infrapoints = FALSE; /* This will be updated if we find
3245 * an placeable extra. */
3246
3247 terrain_control.pythagorean_diagonal
3249 "parameters.pythagorean_diagonal");
3250
3253 "parameters.ocean_resources");
3254
3255 text = secfile_lookup_str_default(file,
3256 N_("?gui_type:Build Type A Base"),
3257 "extraui.ui_name_base_fortress");
3258 sz_strlcpy(terrain_control.gui_type_base0, text);
3259
3260 text = secfile_lookup_str_default(file,
3261 N_("?gui_type:Build Type B Base"),
3262 "extraui.ui_name_base_airbase");
3263 sz_strlcpy(terrain_control.gui_type_base1, text);
3264
3265 if (ok) {
3266 /* Terrain details */
3267
3268 terrain_type_iterate(pterrain) {
3269 const char **slist;
3270 const int i = terrain_index(pterrain);
3271 const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
3272 const char *cstr;
3273 const char *ename;
3274
3275 sz_strlcpy(pterrain->graphic_str,
3276 secfile_lookup_str(file, "%s.graphic", tsection));
3277 sz_strlcpy(pterrain->graphic_alt,
3279 "%s.graphic_alt", tsection));
3280 sz_strlcpy(pterrain->graphic_alt2,
3282 "%s.graphic_alt2", tsection));
3283
3284 pterrain->identifier
3285 = secfile_lookup_str(file, "%s.identifier", tsection)[0];
3286 if ('\0' == pterrain->identifier) {
3288 "\"%s\" [%s] identifier missing value.",
3289 filename, tsection);
3290 ok = FALSE;
3291 break;
3292 }
3293 if (TERRAIN_UNKNOWN_IDENTIFIER == pterrain->identifier) {
3295 "\"%s\" [%s] cannot use '%c' as an identifier;"
3296 " it is reserved for unknown terrain.",
3297 filename, tsection, pterrain->identifier);
3298 ok = FALSE;
3299 break;
3300 }
3301 for (j = T_FIRST; j < i; j++) {
3302 if (pterrain->identifier == terrain_by_number(j)->identifier) {
3304 "\"%s\" [%s] has the same identifier as [%s].",
3305 filename, tsection,
3307 ok = FALSE;
3308 break;
3309 }
3310 }
3311
3312 if (!ok) {
3313 break;
3314 }
3315
3316 cstr = secfile_lookup_str(file, "%s.class", tsection);
3317 pterrain->tclass = terrain_class_by_name(cstr, fc_strcasecmp);
3318 if (!terrain_class_is_valid(pterrain->tclass)) {
3320 "\"%s\": [%s] unknown class \"%s\"",
3321 filename, tsection, cstr);
3322 ok = FALSE;
3323 break;
3324 }
3325
3326 if (!secfile_lookup_int(file, &pterrain->movement_cost,
3327 "%s.movement_cost", tsection)
3328 || !secfile_lookup_int(file, &pterrain->defense_bonus,
3329 "%s.defense_bonus", tsection)) {
3331 ok = FALSE;
3332 break;
3333 }
3334
3336 pterrain->output[o]
3337 = secfile_lookup_int_default(file, 0, "%s.%s", tsection,
3340
3341 res = secfile_lookup_str_vec(file, &nval, "%s.resources", tsection);
3343 "%s.resource_freq", tsection);
3344 if (nval2 > 0 && nval2 != nval) {
3346 "\"%s\": [%s] Different lengths for resources "
3347 "and resource frequencies",
3348 filename, tsection);
3349 ok = FALSE;
3350 }
3351 pterrain->resources = fc_calloc(nval + 1, sizeof(*pterrain->resources));
3352 pterrain->resource_freq = fc_calloc(nval + 1,
3353 sizeof(*pterrain->resource_freq));
3354 for (j = 0; j < nval; j++) {
3355 pterrain->resources[j] = lookup_resource(filename, res[j], tsection);
3356 if (pterrain->resources[j] == NULL) {
3357 ok = FALSE;
3358 break;
3359 }
3360 pterrain->resource_freq[j] = j < nval2
3361 ? res_freq[j]
3363 if (pterrain->resource_freq[j] < RESOURCE_FREQUENCY_MINIMUM
3364 || pterrain->resource_freq[j] > RESOURCE_FREQUENCY_MAXIMUM) {
3366 "\"%s\": [%s] Resource frequency '%d' "
3367 "outside allowed range",
3368 filename, tsection,
3369 pterrain->resource_freq[j]);
3370 ok = FALSE;
3371 break;
3372 }
3373 }
3374 pterrain->resources[nval] = NULL;
3375 /* Terminating zero technically not necessary */
3376 pterrain->resource_freq[nval] = 0;
3377 free(res);
3378 res = NULL;
3379 free(res_freq);
3380 res_freq = NULL;
3381
3382 if (!ok) {
3383 break;
3384 }
3385
3387 pterrain->road_output_incr_pct[o]
3388 = secfile_lookup_int_default(file, 0, "%s.road_%s_incr_pct",
3391
3392 if (!lookup_time(file, &pterrain->base_time, tsection, "base_time",
3393 filename, NULL, &ok)
3394 || !lookup_time(file, &pterrain->road_time, tsection, "road_time",
3395 filename, NULL, &ok)) {
3397 ok = FALSE;
3398 break;
3399 }
3400
3401 if (!lookup_terrain(file, "cultivate_result", filename, pterrain,
3402 &pterrain->cultivate_result, FALSE)) {
3403 ruleset_error(NULL, LOG_ERROR, "%s: No cultivate_result", tsection);
3404 ok = FALSE;
3405 break;
3406 }
3407 if (pterrain->cultivate_result == pterrain) {
3409 "%s: Cultivating result in terrain itself.",
3410 tsection);
3411 ok = FALSE;
3412 break;
3413 }
3414 if (!secfile_lookup_int(file, &pterrain->irrigation_food_incr,
3415 "%s.irrigation_food_incr", tsection)
3416 || !lookup_time(file, &pterrain->irrigation_time,
3417 tsection, "irrigation_time", filename, NULL, &ok)) {
3419 ok = FALSE;
3420 break;
3421 }
3422
3423 if (!lookup_terrain(file, "plant_result", filename, pterrain,
3424 &pterrain->plant_result, FALSE)) {
3425 ruleset_error(NULL, LOG_ERROR, "%s: No plant_result", tsection);
3426 ok = FALSE;
3427 break;
3428 }
3429 if (pterrain->plant_result == pterrain) {
3431 "%s: Planting result in terrain itself.",
3432 tsection);
3433 ok = FALSE;
3434 break;
3435 }
3436 if (!secfile_lookup_int(file, &pterrain->mining_shield_incr,
3437 "%s.mining_shield_incr", tsection)
3438 || !lookup_time(file, &pterrain->mining_time,
3439 tsection, "mining_time", filename, NULL, &ok)) {
3441 ok = FALSE;
3442 break;
3443 }
3444
3445 if (!lookup_time(file, &pterrain->cultivate_time,
3446 tsection, "cultivate_time", filename, NULL, &ok)) {
3448 "%s: Missing cultivate_time", tsection);
3449 ok = FALSE;
3450 break;
3451 }
3452 if ((pterrain->cultivate_result != NULL
3453 && pterrain->cultivate_time <= 0)
3454 || (pterrain->cultivate_result == NULL
3455 && pterrain->cultivate_time > 0)) {
3457 "%s: cultivate_result and cultivate_time disagree "
3458 "whether cultivating is enabled", tsection);
3459 ok = FALSE;
3460 break;
3461 }
3462
3463 if (!lookup_time(file, &pterrain->plant_time,
3464 tsection, "plant_time", filename, NULL, &ok)) {
3466 "%s: Missing plant_time", tsection);
3467 ok = FALSE;
3468 break;
3469 }
3470 if ((pterrain->plant_result != NULL
3471 && pterrain->plant_time <= 0)
3472 || (pterrain->plant_result == NULL
3473 && pterrain->plant_time > 0)) {
3475 "%s: plant_result and plant_time disagree "
3476 "whether planting is enabled", tsection);
3477 ok = FALSE;
3478 break;
3479 }
3480
3481 if (!lookup_unit_type(file, tsection, "animal",
3482 &pterrain->animal, filename,
3483 rule_name_get(&pterrain->name))) {
3484 ok = FALSE;
3485 break;
3486 }
3487
3488 if (!lookup_terrain(file, "transform_result", filename, pterrain,
3489 &pterrain->transform_result, TRUE)) {
3490 ok = FALSE;
3491 break;
3492 }
3493 if (!lookup_time(file, &pterrain->transform_time,
3494 tsection, "transform_time", filename, NULL, &ok)) {
3496 ok = FALSE;
3497 break;
3498 }
3499 if ((pterrain->transform_result != NULL
3500 && pterrain->transform_time <= 0)
3501 || (pterrain->transform_result == NULL
3502 && pterrain->transform_time > 0)) {
3504 "%s: transform_result and transform_time disagree "
3505 "whether transforming is enabled", tsection);
3506 ok = FALSE;
3507 break;
3508 }
3509
3510 pterrain->placing_time = 1; /* Default */
3511 lookup_time(file, &pterrain->placing_time,
3512 tsection, "placing_time", filename, NULL, &ok);
3513
3514 pterrain->pillage_time = 1; /* Default */
3515 lookup_time(file, &pterrain->pillage_time,
3516 tsection, "pillage_time", filename, NULL, &ok);
3517
3518 if (!lookup_terrain(file, "warmer_wetter_result", filename, pterrain,
3519 &pterrain->warmer_wetter_result, TRUE)
3520 || !lookup_terrain(file, "warmer_drier_result", filename, pterrain,
3521 &pterrain->warmer_drier_result, TRUE)
3522 || !lookup_terrain(file, "cooler_wetter_result", filename, pterrain,
3523 &pterrain->cooler_wetter_result, TRUE)
3524 || !lookup_terrain(file, "cooler_drier_result", filename, pterrain,
3525 &pterrain->cooler_drier_result, TRUE)) {
3526 ok = FALSE;
3527 break;
3528 }
3529
3530 /* Set default removal times */
3531 extra_type_iterate(pextra) {
3532 pterrain->extra_removal_times[extra_index(pextra)] = 0;
3534
3535 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
3536 if (!rscompat_terrain_extra_rmtime_3_2(file, tsection, pterrain)) {
3537 ok = FALSE;
3538 break;
3539 }
3540 }
3541
3542 for (j = 0; (ename = secfile_lookup_str_default(file, NULL,
3543 "%s.extra_settings%d.extra",
3544 tsection, j)); j++) {
3545 const struct extra_type *pextra = extra_type_by_rule_name(ename);
3546
3547 if (pextra != NULL) {
3548 char time_sections[512];
3549
3551 "%s.extra_settings%d", tsection, j);
3552
3553 lookup_time(file, &pterrain->extra_removal_times[extra_index(pextra)],
3554 time_sections, "removal_time", filename, NULL, &ok);
3555 } else {
3557 "\"%s\" [%s] has settings for unknown extra \"%s\".",
3558 filename, tsection, ename);
3559 ok = FALSE;
3560 break;
3561 }
3562 }
3563
3564 if (ok) {
3565 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsection);
3566 BV_CLR_ALL(pterrain->flags);
3567 for (j = 0; j < nval; j++) {
3568 const char *sval = slist[j];
3569 enum terrain_flag_id flag
3571
3572 if (!terrain_flag_id_is_valid(flag)) {
3574 "\"%s\" [%s] has unknown flag \"%s\".",
3575 filename, tsection, sval);
3576 ok = FALSE;
3577 break;
3578 } else {
3579 BV_SET(pterrain->flags, flag);
3580 }
3581 }
3582
3583 free(slist);
3584 }
3585
3586 if (!ok) {
3587 break;
3588 }
3589
3590 {
3592
3596 pterrain->property[mtp]
3597 = secfile_lookup_int_default(file, 0, "%s.property_%s", tsection,
3599 }
3600 }
3601
3602 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
3603 BV_CLR_ALL(pterrain->native_to);
3604 for (j = 0; j < nval; j++) {
3605 struct unit_class *class = unit_class_by_rule_name(slist[j]);
3606
3607 if (!class) {
3609 "\"%s\" [%s] is native to unknown unit class \"%s\".",
3610 filename, tsection, slist[j]);
3611 ok = FALSE;
3612 break;
3613 } else {
3614 BV_SET(pterrain->native_to, uclass_index(class));
3615 }
3616 }
3617 free(slist);
3618
3619 if (!ok) {
3620 break;
3621 }
3622
3623 /* Get terrain color */
3624 {
3625 fc_assert_ret_val(pterrain->rgb == NULL, FALSE);
3626
3627 if (!rgbcolor_load(file, &pterrain->rgb, "%s.color", tsection)) {
3629 "Missing terrain color definition: %s",
3630 secfile_error());
3631 ok = FALSE;
3632 break;
3633 }
3634 }
3635
3636 pterrain->helptext = lookup_strvec(file, tsection, "helptext");
3638 }
3639
3640 if (ok) {
3641 /* Extra details */
3642 extra_type_iterate(pextra) {
3643 BV_CLR_ALL(pextra->conflicts);
3645
3646 extra_type_iterate(pextra) {
3647 int eidx = extra_index(pextra);
3648 const char *section = &extra_sections[eidx * MAX_SECTION_LABEL];
3649 const char **slist;
3650 struct requirement_vector *reqs;
3651 const char *catname;
3652 int cj;
3653 enum extra_cause cause;
3655 const char *eus_name;
3656 const char *vis_req_name;
3657 const struct advance *vis_req;
3658
3659 catname = secfile_lookup_str(file, "%s.category", section);
3660 if (catname == NULL) {
3662 "\"%s\" extra \"%s\" has no category.",
3663 filename, extra_rule_name(pextra));
3664 ok = FALSE;
3665 break;
3666 }
3667 pextra->category = extra_category_by_name(catname, fc_strcasecmp);
3668 if (!extra_category_is_valid(pextra->category)) {
3670 "\"%s\" extra \"%s\" has invalid category \"%s\".",
3671 filename, extra_rule_name(pextra), catname);
3672 ok = FALSE;
3673 break;
3674 }
3675
3676 slist = secfile_lookup_str_vec(file, &nval, "%s.causes", section);
3677 pextra->causes = 0;
3678 for (cj = 0; cj < nval; cj++) {
3679 const char *sval = slist[cj];
3681
3682 if (!extra_cause_is_valid(cause)) {
3684 "\"%s\" extra \"%s\": unknown cause \"%s\".",
3685 filename, extra_rule_name(pextra), sval);
3686 ok = FALSE;
3687 break;
3688 } else {
3689 pextra->causes |= (1 << cause);
3690 extra_to_caused_by_list(pextra, cause);
3691 }
3692 }
3693
3694 if (pextra->causes == 0) {
3695 /* Extras that do not have any causes added to EC_NONE list */
3697 }
3698
3699 if (!is_extra_caused_by(pextra, EC_BASE)
3700 && !is_extra_caused_by(pextra, EC_ROAD)
3701 && !is_extra_caused_by(pextra, EC_RESOURCE)) {
3702 /* Not a base, road, nor resource, so special */
3703 pextra->data.special_idx = extra_type_list_size(extra_type_list_by_cause(EC_SPECIAL));
3705 }
3706
3707 free(slist);
3708
3709 /* Handle before rscompat_extra_rmcause_3_2() might need the values */
3710 pextra->removal_time = 0; /* Default */
3711 lookup_time(file, &pextra->removal_time, section, "removal_time",
3712 filename, extra_rule_name(pextra), &ok);
3713 pextra->removal_time_factor
3714 = secfile_lookup_int_default(file, 1, "%s.removal_time_factor",
3715 section);
3716
3717 /* Do not clear after this point.
3718 * rscompat_extra_rmcause_3_2() might set a flag we want to keep. */
3719 BV_CLR_ALL(pextra->flags);
3720
3721 slist = secfile_lookup_str_vec(file, &nval, "%s.rmcauses", section);
3722 pextra->rmcauses = 0;
3723 for (j = 0; j < nval; j++) {
3724 const char *sval = slist[j];
3725
3726 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
3728 }
3729
3731
3734 "\"%s\" extra \"%s\": unknown rmcause \"%s\".",
3735 filename, extra_rule_name(pextra), sval);
3736 ok = FALSE;
3737 break;
3738 } else {
3739 pextra->rmcauses |= (1 << rmcause);
3741 }
3742 }
3743
3744 free(slist);
3745
3746 sz_strlcpy(pextra->activity_gfx,
3748 "%s.activity_gfx", section));
3749 sz_strlcpy(pextra->act_gfx_alt,
3751 "%s.act_gfx_alt", section));
3752 sz_strlcpy(pextra->act_gfx_alt2,
3754 "%s.act_gfx_alt2", section));
3755 sz_strlcpy(pextra->rmact_gfx,
3757 "%s.rmact_gfx", section));
3758 sz_strlcpy(pextra->rmact_gfx_alt,
3760 "%s.rmact_gfx_alt", section));
3761 sz_strlcpy(pextra->rmact_gfx_alt2,
3763 "%s.rmact_gfx_alt2", section));
3764 sz_strlcpy(pextra->graphic_str,
3765 secfile_lookup_str_default(file, "-", "%s.graphic", section));
3766 sz_strlcpy(pextra->graphic_alt,
3768 "%s.graphic_alt", section));
3769
3770 reqs = lookup_req_list(file, compat, section, "reqs", extra_rule_name(pextra));
3771 if (reqs == NULL) {
3772 ok = FALSE;
3773 break;
3774 }
3775 requirement_vector_copy(&pextra->reqs, reqs);
3776
3777 reqs = lookup_req_list(file, compat, section, "rmreqs", extra_rule_name(pextra));
3778 if (reqs == NULL) {
3779 ok = FALSE;
3780 break;
3781 }
3782 requirement_vector_copy(&pextra->rmreqs, reqs);
3783
3784 reqs = lookup_req_list(file, compat, section, "appearance_reqs", extra_rule_name(pextra));
3785 if (reqs == NULL) {
3786 ok = FALSE;
3787 break;
3788 }
3789 requirement_vector_copy(&pextra->appearance_reqs, reqs);
3790
3791 reqs = lookup_req_list(file, compat, section, "disappearance_reqs", extra_rule_name(pextra));
3792 if (reqs == NULL) {
3793 ok = FALSE;
3794 break;
3795 }
3796 requirement_vector_copy(&pextra->disappearance_reqs, reqs);
3797
3798 pextra->buildable = secfile_lookup_bool_default(file,
3800 "%s.buildable", section);
3801 pextra->generated = secfile_lookup_bool_default(file, TRUE,
3802 "%s.generated", section);
3803
3804 pextra->build_time = 0; /* Default */
3805 lookup_time(file, &pextra->build_time, section, "build_time",
3806 filename, extra_rule_name(pextra), &ok);
3807 pextra->build_time_factor = secfile_lookup_int_default(file, 1,
3808 "%s.build_time_factor", section);
3809
3810 /* removal_time handled earlier, so that rscompat_extra_rmcause_3_2()
3811 * can use them. */
3812
3813 pextra->infracost = secfile_lookup_int_default(file, 0,
3814 "%s.infracost", section);
3815 if (pextra->infracost > 0) {
3816 terrain_control.infrapoints = TRUE;
3817 }
3818
3819 pextra->defense_bonus = secfile_lookup_int_default(file, 0,
3820 "%s.defense_bonus",
3821 section);
3822 if (pextra->defense_bonus != 0) {
3823 if (extra_has_flag(pextra, EF_NATURAL_DEFENSE)) {
3825 } else {
3827 }
3828 }
3829
3830 eus_name = secfile_lookup_str_default(file, "Normal", "%s.unit_seen", section);
3832 if (!extra_unit_seen_type_is_valid(pextra->eus)) {
3834 "\"%s\" extra \"%s\" has illegal unit_seen value \"%s\".",
3835 filename, extra_rule_name(pextra), eus_name);
3836 ok = FALSE;
3837 break;
3838 }
3839 if (pextra->eus == EUS_HIDDEN) {
3841 }
3842
3843 pextra->appearance_chance = secfile_lookup_int_default(file, RS_DEFAULT_EXTRA_APPEARANCE,
3844 "%s.appearance_chance",
3845 section);
3846 pextra->disappearance_chance = secfile_lookup_int_default(file,
3848 "%s.disappearance_chance",
3849 section);
3850
3851 pextra->no_aggr_near_city = secfile_lookup_int_default(file, -1,
3852 "%s.no_aggr_near_city",
3853 section);
3854
3855 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
3856 BV_CLR_ALL(pextra->native_to);
3857 for (j = 0; j < nval; j++) {
3858 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
3859
3860 if (uclass == NULL) {
3862 "\"%s\" extra \"%s\" is native to unknown unit class \"%s\".",
3863 filename, extra_rule_name(pextra), slist[j]);
3864 ok = FALSE;
3865 break;
3866 } else {
3867 BV_SET(pextra->native_to, uclass_index(uclass));
3868 }
3869 }
3870 free(slist);
3871
3872 if (!ok) {
3873 break;
3874 }
3875
3876 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
3877 for (j = 0; j < nval; j++) {
3878 const char *sval = slist[j];
3879 enum extra_flag_id flag;
3880
3881 if (compat->compat_mode && compat->version < RSFORMAT_3_2
3882 && !fc_strcasecmp("NoAggressive", sval)) {
3883 if (pextra->no_aggr_near_city >= 0) {
3885 "\"%s\" extra \"%s\" has both no_aggr_near_city set and old style "
3886 "NoAggressive flag",
3887 filename, extra_rule_name(pextra));
3888 ok = FALSE;
3889 break;
3890 }
3891 /* Old NoAggressive flag meant distance of 3. */
3892 pextra->no_aggr_near_city = 3;
3893 } else {
3894
3896
3897 if (!extra_flag_id_is_valid(flag)) {
3899 "\"%s\" extra \"%s\": unknown flag \"%s\".",
3900 filename, extra_rule_name(pextra), sval);
3901 ok = FALSE;
3902 break;
3903 } else {
3904 BV_SET(pextra->flags, flag);
3905 }
3906 }
3907 }
3908 free(slist);
3909
3910 if (pextra->no_aggr_near_city >= 0) {
3912 }
3913
3914 if (extra_has_flag(pextra, EF_CAUSE_ZOC)) {
3916 }
3917
3918 if (!ok) {
3919 break;
3920 }
3921
3922 slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
3923 for (j = 0; j < nval; j++) {
3924 const char *sval = slist[j];
3926
3927 if (pextra2 == NULL) {
3929 "\"%s\" extra \"%s\": unknown conflict extra \"%s\".",
3930 filename, extra_rule_name(pextra), sval);
3931 ok = FALSE;
3932 break;
3933 } else {
3934 BV_SET(pextra->conflicts, extra_index(pextra2));
3935 BV_SET(pextra2->conflicts, extra_index(pextra));
3936 }
3937 }
3938
3939 free(slist);
3940
3941 if (!ok) {
3942 break;
3943 }
3944
3945 slist = secfile_lookup_str_vec(file, &nval, "%s.hidden_by", section);
3946 BV_CLR_ALL(pextra->hidden_by);
3947 for (j = 0; j < nval; j++) {
3948 const char *sval = slist[j];
3949 const struct extra_type *top = extra_type_by_rule_name(sval);
3950
3951 if (top == NULL) {
3953 "\"%s\" extra \"%s\" hidden by unknown extra \"%s\".",
3954 filename, extra_rule_name(pextra), sval);
3955 ok = FALSE;
3956 break;
3957 } else {
3958 BV_SET(pextra->hidden_by, extra_index(top));
3959 }
3960 }
3961 free(slist);
3962
3963 if (!ok) {
3964 break;
3965 }
3966
3967 slist = secfile_lookup_str_vec(file, &nval, "%s.bridged_over", section);
3968 BV_CLR_ALL(pextra->bridged_over);
3969 for (j = 0; j < nval; j++) {
3970 const char *sval = slist[j];
3971 const struct extra_type *top = extra_type_by_rule_name(sval);
3972
3973 if (top == NULL) {
3975 "\"%s\" extra \"%s\" bridged over unknown extra \"%s\".",
3976 filename, extra_rule_name(pextra), sval);
3977 ok = FALSE;
3978 break;
3979 } else {
3980 BV_SET(pextra->bridged_over, extra_index(top));
3981 }
3982 }
3983 free(slist);
3984
3985 if (!ok) {
3986 break;
3987 }
3988
3990 "%s.visibility_req", section);
3992
3993 if (vis_req == NULL) {
3995 "\"%s\" %s: unknown visibility_req %s.",
3996 filename, section, vis_req_name);
3997 ok = FALSE;
3998 break;
3999 }
4000
4001 pextra->visibility_req = advance_number(vis_req);
4002
4003 pextra->helptext = lookup_strvec(file, section, "helptext");
4004
4005 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
4007 }
4009 }
4010
4011 if (ok) {
4012 int i = 0;
4013 /* Resource details */
4014
4016 char identifier[MAX_LEN_NAME];
4017 const char *id;
4019
4020 if (!presource->data.resource) {
4022 "\"%s\" extra \"%s\" has \"Resource\" cause but no "
4023 "corresponding [resource_*] section",
4024 filename, extra_rule_name(presource));
4025 ok = FALSE;
4026 break;
4027 }
4028
4030 presource->data.resource->output[o] =
4031 secfile_lookup_int_default(file, 0, "%s.%s", rsection,
4034
4035 id = secfile_lookup_str_default(file, NULL, "%s.identifier", rsection);
4036
4037 if (id == NULL) {
4038 presource->data.resource->id_old_save = '\0';
4039 } else {
4040 sz_strlcpy(identifier, id);
4041
4042 presource->data.resource->id_old_save = identifier[0];
4043 if (RESOURCE_NULL_IDENTIFIER == presource->data.resource->id_old_save) {
4045 "\"%s\" [%s] identifier missing value.",
4046 filename, rsection);
4047 ok = FALSE;
4048 break;
4049 }
4050 if (RESOURCE_NONE_IDENTIFIER == presource->data.resource->id_old_save) {
4052 "\"%s\" [%s] cannot use '%c' as an identifier;"
4053 " it is reserved.",
4054 filename, rsection, presource->data.resource->id_old_save);
4055 ok = FALSE;
4056 break;
4057 }
4058 }
4059
4060 if (!ok) {
4061 break;
4062 }
4063
4064 i++;
4066
4067 for (j = 0; ok && j < game.control.num_resource_types; j++) {
4068 const char *section = &resource_sections[j * MAX_SECTION_LABEL];
4069 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4071
4072 if (!is_extra_caused_by(pextra, EC_RESOURCE)) {
4074 "\"%s\" resource section [%s]: extra \"%s\" does not "
4075 "have \"Resource\" in its causes",
4076 filename, section, extra_name);
4077 ok = FALSE;
4078 }
4079 }
4080 }
4081
4082 if (ok) {
4083 /* This can't be part of previous loop as we don't want random data from previous
4084 * ruleset to play havoc on us when we have only some resource identifiers loaded
4085 * from the new ruleset. */
4087 if (pres->data.resource->id_old_save != '\0') {
4089 if (pres->data.resource->id_old_save == pres2->data.resource->id_old_save
4090 && pres != pres2) {
4092 "\"%s\" [%s] has the same identifier as [%s].",
4093 filename,
4096 ok = FALSE;
4097 break;
4098 }
4100
4101 if (!ok) {
4102 break;
4103 }
4104 }
4106 }
4107
4108 if (ok) {
4109 /* Base details */
4111 struct base_type *pbase = extra_base_get(pextra);
4112 const char *section;
4113 const char *gui_str;
4114
4115 if (!pbase) {
4117 "\"%s\" extra \"%s\" has \"Base\" cause but no "
4118 "corresponding [base_*] section",
4119 filename, extra_rule_name(pextra));
4120 ok = FALSE;
4121 break;
4122 }
4124
4125 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4127 if (!base_gui_type_is_valid(pbase->gui_type)) {
4129 "\"%s\" base \"%s\": unknown gui_type \"%s\".",
4130 filename, extra_rule_name(pextra), gui_str);
4131 ok = FALSE;
4132 break;
4133 }
4134
4135 pbase->border_sq = secfile_lookup_int_default(file, -1, "%s.border_sq",
4136 section);
4137 pbase->vision_main_sq = secfile_lookup_int_default(file, -1,
4138 "%s.vision_main_sq",
4139 section);
4140 pbase->vision_invis_sq = secfile_lookup_int_default(file, -1,
4141 "%s.vision_invis_sq",
4142 section);
4143 pbase->vision_subs_sq = secfile_lookup_int_default(file, -1,
4144 "%s.vision_subs_sq",
4145 section);
4146
4147 if (!ok) {
4148 break;
4149 }
4150
4153
4155 struct base_type *pbase2;
4156
4157 if (pextra == pextra2) {
4158 /* End of the fully initialized bases iteration. */
4159 break;
4160 }
4161
4164 BV_SET(pextra->conflicts, extra_index(pextra2));
4165 BV_SET(pextra2->conflicts, extra_index(pextra));
4166 }
4168 }
4170
4171 for (j = 0; ok && j < game.control.num_base_types; j++) {
4172 const char *section = &base_sections[j * MAX_SECTION_LABEL];
4173 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4175
4176 if (!is_extra_caused_by(pextra, EC_BASE)) {
4178 "\"%s\" base section [%s]: extra \"%s\" does not have "
4179 "\"Base\" in its causes",
4180 filename, section, extra_name);
4181 ok = FALSE;
4182 }
4183 }
4184 }
4185
4186 if (ok) {
4188 struct road_type *proad = extra_road_get(pextra);
4189 const char *section;
4190 const char **slist;
4191 const char *special;
4192 const char *modestr;
4193 struct requirement_vector *reqs;
4194 const char *gui_str;
4195
4196 if (!proad) {
4198 "\"%s\" extra \"%s\" has \"Road\" cause but no "
4199 "corresponding [road_*] section",
4200 filename, extra_rule_name(pextra));
4201 ok = FALSE;
4202 break;
4203 }
4205
4206 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4208 if (!road_gui_type_is_valid(proad->gui_type)) {
4210 "\"%s\" road \"%s\": unknown gui_type \"%s\".",
4211 filename, extra_rule_name(pextra), gui_str);
4212 ok = FALSE;
4213 break;
4214 }
4215
4216 reqs = lookup_req_list(file, compat, section, "first_reqs", extra_rule_name(pextra));
4217 if (reqs == NULL) {
4218 ok = FALSE;
4219 break;
4220 }
4221 requirement_vector_copy(&proad->first_reqs, reqs);
4222
4223 if (!secfile_lookup_int(file, &proad->move_cost,
4224 "%s.move_cost", section)) {
4225 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4226 ok = FALSE;
4227 break;
4228 }
4229
4230 modestr = secfile_lookup_str_default(file, "FastAlways", "%s.move_mode",
4231 section);
4233 if (!road_move_mode_is_valid(proad->move_mode)) {
4235 "Illegal move_mode \"%s\" for road \"%s\"",
4236 modestr, extra_rule_name(pextra));
4237 ok = FALSE;
4238 break;
4239 }
4240
4242 proad->tile_incr_const[o] =
4243 secfile_lookup_int_default(file, 0, "%s.%s_incr_const",
4245 proad->tile_incr[o] =
4246 secfile_lookup_int_default(file, 0, "%s.%s_incr",
4248 proad->tile_bonus[o] =
4249 secfile_lookup_int_default(file, 0, "%s.%s_bonus",
4252
4253 special = secfile_lookup_str_default(file, "None", "%s.compat_special", section);
4254 if (!fc_strcasecmp(special, "Road")) {
4255 if (compat_road) {
4257 "Multiple roads marked as compatibility \"Road\"");
4258 ok = FALSE;
4259 }
4260 compat_road = TRUE;
4261 proad->compat = ROCO_ROAD;
4262 } else if (!fc_strcasecmp(special, "Railroad")) {
4263 if (compat_rail) {
4265 "Multiple roads marked as compatibility \"Railroad\"");
4266 ok = FALSE;
4267 }
4268 compat_rail = TRUE;
4269 proad->compat = ROCO_RAILROAD;
4270 } else if (!fc_strcasecmp(special, "River")) {
4271 if (compat_river) {
4273 "Multiple roads marked as compatibility \"River\"");
4274 ok = FALSE;
4275 }
4277 proad->compat = ROCO_RIVER;
4278 } else if (!fc_strcasecmp(special, "None")) {
4279 proad->compat = ROCO_NONE;
4280 } else {
4282 "Illegal compatibility special \"%s\" for road %s",
4283 special, extra_rule_name(pextra));
4284 ok = FALSE;
4285 }
4286
4287 if (!ok) {
4288 break;
4289 }
4290
4291 slist = secfile_lookup_str_vec(file, &nval, "%s.integrates", section);
4292 BV_CLR_ALL(proad->integrates);
4293 for (j = 0; j < nval; j++) {
4294 const char *sval = slist[j];
4296 struct road_type *top = NULL;
4297
4298 if (textra != NULL) {
4299 top = extra_road_get(textra);
4300 }
4301
4302 if (top == NULL) {
4304 "\"%s\" road \"%s\" integrates with unknown road \"%s\".",
4305 filename, extra_rule_name(pextra), sval);
4306 ok = FALSE;
4307 break;
4308 } else {
4309 BV_SET(proad->integrates, road_number(top));
4310 }
4311 }
4312 free(slist);
4313
4314 if (!ok) {
4315 break;
4316 }
4317
4318 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
4319 BV_CLR_ALL(proad->flags);
4320 for (j = 0; j < nval; j++) {
4321 const char *sval = slist[j];
4323
4324 if (!road_flag_id_is_valid(flag)) {
4326 "\"%s\" road \"%s\": unknown flag \"%s\".",
4327 filename, extra_rule_name(pextra), sval);
4328 ok = FALSE;
4329 break;
4330 } else {
4331 BV_SET(proad->flags, flag);
4332 }
4333 }
4334 free(slist);
4335
4336 if (!ok) {
4337 break;
4338 }
4340
4341 for (j = 0; ok && j < game.control.num_road_types; j++) {
4342 const char *section = &road_sections[j * MAX_SECTION_LABEL];
4343 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4345
4346 if (!is_extra_caused_by(pextra, EC_ROAD)) {
4348 "\"%s\" road section [%s]: extra \"%s\" does not have "
4349 "\"Road\" in its causes",
4350 filename, section, extra_name);
4351 ok = FALSE;
4352 }
4353 }
4354 }
4355
4356 if (ok) {
4357 extra_type_iterate(pextra) {
4358 pextra->bridged = extra_type_list_new();
4360 if (BV_ISSET(pextra->bridged_over, pbridged->id)) {
4361 extra_type_list_append(pextra->bridged, pbridged);
4362 }
4365 }
4366
4367 if (ok) {
4369 }
4370
4371 return ok;
4372}
4373
4374/**********************************************************************/
4378static bool load_government_names(struct section_file *file,
4379 struct rscompat_info *compat)
4380{
4381 int nval = 0;
4382 struct section_list *sec;
4383 const char *filename = secfile_name(file);
4384 bool ok = TRUE;
4385
4386 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4387 return FALSE;
4388 }
4389
4390 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4391 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4392
4394 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
4395 ruleset_error(NULL, LOG_ERROR, "\"%s\": No governments?!?", filename);
4396 ok = FALSE;
4397 } else if (nval > G_LAST) {
4399 "\"%s\": Too many governments (%d, max %d)",
4400 filename, nval, G_LAST);
4401 ok = FALSE;
4402 }
4403
4404 if (ok) {
4406
4407 /* Government names are needed early so that get_government_by_name will
4408 * work. */
4409 governments_iterate(gov) {
4410 const char *sec_name =
4412
4413 if (!ruleset_load_names(&gov->name, NULL, file, sec_name)) {
4414 ok = FALSE;
4415 break;
4416 }
4418 }
4419
4421
4422 if (ok) {
4424 nval = (NULL != sec ? section_list_size(sec) : 0);
4425
4426 if (nval > MAX_NUM_MULTIPLIERS) {
4428 "\"%s\": Too many multipliers (%d, max %d)",
4429 filename, nval, MAX_NUM_MULTIPLIERS);
4430
4431 ok = FALSE;
4432 } else {
4434 }
4435
4436 if (ok) {
4437 multipliers_iterate(pmul) {
4438 const char *sec_name =
4440
4441 if (!ruleset_load_names(&pmul->name, NULL, file, sec_name)) {
4443 "\"%s\": Cannot load multiplier names",
4444 filename);
4445 ok = FALSE;
4446 break;
4447 }
4449 }
4450 }
4451
4453
4454 return ok;
4455}
4456
4457/**********************************************************************/
4461 struct rscompat_info *compat)
4462{
4463 struct section_list *sec;
4464 const char *filename = secfile_name(file);
4465 bool ok = TRUE;
4466
4468
4470 = lookup_government(file, "governments.during_revolution", filename, NULL);
4472 ok = FALSE;
4473 }
4474
4475 if (ok) {
4478
4479 /* Easy ones: */
4481 const int i = government_index(g);
4482 const char *sec_name = section_name(section_list_get(sec, i));
4483 struct requirement_vector *reqs
4485
4486 if (reqs == NULL) {
4487 ok = FALSE;
4488 break;
4489 }
4490
4491 if (NULL != secfile_entry_lookup(file, "%s.ai_better", sec_name)) {
4492 char entry[100];
4493
4494 fc_snprintf(entry, sizeof(entry), "%s.ai_better", sec_name);
4495 g->ai.better = lookup_government(file, entry, filename, NULL);
4496 if (g->ai.better == NULL) {
4497 ok = FALSE;
4498 break;
4499 }
4500 } else {
4501 g->ai.better = NULL;
4502 }
4503 requirement_vector_copy(&g->reqs, reqs);
4504
4505 sz_strlcpy(g->graphic_str,
4506 secfile_lookup_str(file, "%s.graphic", sec_name));
4507 sz_strlcpy(g->graphic_alt,
4508 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
4509 sz_strlcpy(g->sound_str,
4510 secfile_lookup_str_default(file, "-", "%s.sound", sec_name));
4511 sz_strlcpy(g->sound_alt,
4512 secfile_lookup_str_default(file, "-", "%s.sound_alt", sec_name));
4513 sz_strlcpy(g->sound_alt2,
4514 secfile_lookup_str_default(file, "-", "%s.sound_alt2", sec_name));
4515
4516 g->helptext = lookup_strvec(file, sec_name, "helptext");
4518 }
4519
4520
4521 if (ok) {
4522 /* Titles */
4524 const char *sec_name
4526 const char *male, *female;
4527
4528 if (!(male = secfile_lookup_str(file, "%s.ruler_male_title", sec_name))
4529 || !(female = secfile_lookup_str(file, "%s.ruler_female_title",
4530 sec_name))) {
4532 "Lack of default ruler titles for "
4533 "government \"%s\" (nb %d): %s",
4535 secfile_error());
4536 ok = FALSE;
4537 break;
4538 } else if (NULL == government_ruler_title_new(g, NULL, male, female)) {
4540 "Lack of default ruler titles for "
4541 "government \"%s\" (nb %d).",
4543 ok = FALSE;
4544 break;
4545 }
4547 }
4548
4550
4551 if (ok) {
4553 multipliers_iterate(pmul) {
4554 int id = multiplier_index(pmul);
4555 const char *sec_name = section_name(section_list_get(sec, id));
4556 struct requirement_vector *reqs;
4557
4558 if (!secfile_lookup_int(file, &pmul->start, "%s.start", sec_name)) {
4559 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4560 ok = FALSE;
4561 break;
4562 }
4563 if (!secfile_lookup_int(file, &pmul->stop, "%s.stop", sec_name)) {
4564 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4565 ok = FALSE;
4566 break;
4567 }
4568 if (pmul->stop <= pmul->start) {
4570 "Multiplier \"%s\" stop (%d) must be greater "
4571 "than start (%d)", multiplier_rule_name(pmul),
4572 pmul->stop, pmul->start);
4573 ok = FALSE;
4574 break;
4575 }
4576 if (!secfile_lookup_int(file, &pmul->step, "%s.step", sec_name)) {
4577 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4578 ok = FALSE;
4579 break;
4580 }
4581 if (((pmul->stop - pmul->start) % pmul->step) != 0) {
4583 "Multiplier \"%s\" step (%d) does not fit "
4584 "exactly into interval start-stop (%d to %d)",
4585 multiplier_rule_name(pmul), pmul->step,
4586 pmul->start, pmul->stop);
4587 ok = FALSE;
4588 break;
4589 }
4590 if (!secfile_lookup_int(file, &pmul->def, "%s.default", sec_name)) {
4591 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4592 ok = FALSE;
4593 break;
4594 }
4595 if (pmul->def < pmul->start || pmul->def > pmul->stop) {
4597 "Multiplier \"%s\" default (%d) not within "
4598 "legal range (%d to %d)", multiplier_rule_name(pmul),
4599 pmul->def, pmul->start, pmul->stop);
4600 ok = FALSE;
4601 break;
4602 }
4603 if (((pmul->def - pmul->start) % pmul->step) != 0) {
4605 "Multiplier \"%s\" default (%d) not legal "
4606 "with respect to step size %d",
4607 multiplier_rule_name(pmul), pmul->def, pmul->step);
4608 ok = FALSE;
4609 break;
4610 }
4611 pmul->offset = secfile_lookup_int_default(file, 0,
4612 "%s.offset", sec_name);
4613 pmul->factor = secfile_lookup_int_default(file, 100,
4614 "%s.factor", sec_name);
4615 if (pmul->factor == 0) {
4617 "Multiplier \"%s\" scaling factor must "
4618 "not be zero", multiplier_rule_name(pmul));
4619 ok = FALSE;
4620 break;
4621 }
4622
4623 pmul->minimum_turns = secfile_lookup_int_default(file, 0,
4624 "%s.minimum_turns",
4625 sec_name);
4626
4627 reqs = lookup_req_list(file, compat, sec_name, "reqs",
4628 multiplier_rule_name(pmul));
4629 if (reqs == NULL) {
4630 ok = FALSE;
4631 break;
4632 }
4633 requirement_vector_copy(&pmul->reqs, reqs);
4634
4635 pmul->helptext = lookup_strvec(file, sec_name, "helptext");
4638 }
4639
4640 if (ok) {
4642 }
4643
4644 return ok;
4645}
4646
4647/**********************************************************************/
4658static void send_ruleset_control(struct conn_list *dest)
4659{
4661 int idx = 0;
4662
4664
4665 if (game.ruleset_summary != NULL) {
4666 struct packet_ruleset_summary summary;
4667
4669
4670 lsend_packet_ruleset_summary(dest, &summary);
4671 }
4672
4673 while (desc_left > 0) {
4675 int this_len = desc_left;
4676
4677 if (this_len > MAX_LEN_CONTENT - 21) {
4679 }
4680
4681 part.text[this_len] = '\0';
4682
4684 idx += this_len;
4686
4688 }
4689}
4690
4691/**********************************************************************/
4696static const char *check_leader_names(struct nation_type *pnation)
4697{
4699 const char *name = nation_leader_name(pleader);
4700
4702 if (prev_leader == pleader) {
4703 break;
4704 } else if (0 == fc_strcasecmp(name, nation_leader_name(prev_leader))) {
4705 return name;
4706 }
4709 return NULL;
4710}
4711
4712/**********************************************************************/
4716static bool load_nation_names(struct section_file *file,
4717 struct rscompat_info *compat)
4718{
4719 struct section_list *sec;
4720 int j;
4721 bool ok = TRUE;
4722 const char *filename = secfile_name(file);
4723
4724 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4725 return FALSE;
4726 }
4727
4728 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4729 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4730
4732 if (NULL == sec) {
4734 "No available nations in this ruleset!");
4735 ok = FALSE;
4736 } else if (section_list_size(sec) > MAX_NUM_NATIONS) {
4738 "Too many nations (max %d, we have %d)!",
4740 ok = FALSE;
4741 } else {
4744
4746 const int i = nation_index(pl);
4747 const char *sec_name = section_name(section_list_get(sec, i));
4748 const char *domain = secfile_lookup_str_default(file, NULL,
4749 "%s.translation_domain", sec_name);
4750 const char *noun_plural = secfile_lookup_str(file,
4751 "%s.plural", sec_name);
4752
4753
4754 if (domain == NULL) {
4755 domain = "freeciv-nations";
4756 }
4757
4758 if (!strcmp("freeciv-core", domain)) {
4759 pl->translation_domain = NULL;
4760 } else if (!strcmp("freeciv-nations", domain)) {
4761 pl->translation_domain = fc_strdup(domain);
4762 } else {
4764 "Unsupported translation domain \"%s\" for %s",
4765 domain, sec_name);
4766 ok = FALSE;
4767 break;
4768 }
4769
4770 if (!ruleset_load_names(&pl->adjective, pl->translation_domain, file, sec_name)) {
4771 ok = FALSE;
4772 break;
4773 }
4774 name_set(&pl->noun_plural, pl->translation_domain, noun_plural);
4775
4776 /* Check if nation name is already defined. */
4777 for (j = 0; j < i && ok; j++) {
4778 struct nation_type *n2 = nation_by_number(j);
4779
4780 /* Compare strings after stripping off qualifiers -- we don't want
4781 * two nations to end up with identical adjectives displayed to users.
4782 * (This check only catches English, not localisations, of course.) */
4783 if (0 == strcmp(Qn_(untranslated_name(&n2->adjective)),
4784 Qn_(untranslated_name(&pl->adjective)))) {
4786 "Two nations defined with the same adjective \"%s\": "
4787 "in section \'%s\' and section \'%s\'",
4788 Qn_(untranslated_name(&pl->adjective)),
4790 ok = FALSE;
4791 } else if (!strcmp(rule_name_get(&n2->adjective),
4792 rule_name_get(&pl->adjective))) {
4793 /* We cannot have the same rule name, as the game needs them to be
4794 * distinct. */
4796 "Two nations defined with the same rule_name \"%s\": "
4797 "in section \'%s\' and section \'%s\'",
4798 rule_name_get(&pl->adjective),
4800 ok = FALSE;
4801 } else if (0 == strcmp(Qn_(untranslated_name(&n2->noun_plural)),
4802 Qn_(untranslated_name(&pl->noun_plural)))) {
4803 /* We don't want identical English plural names either. */
4805 "Two nations defined with the same plural name \"%s\": "
4806 "in section \'%s\' and section \'%s\'",
4807 Qn_(untranslated_name(&pl->noun_plural)),
4809 ok = FALSE;
4810 }
4811 }
4812 if (!ok) {
4813 break;
4814 }
4816 }
4817
4819
4820 if (ok) {
4822 if (sec != NULL) {
4824
4825 section_list_iterate(sec, psection) {
4826 struct nation_group *pgroup;
4827 const char *name;
4828
4829 name = secfile_lookup_str(file, "%s.name", section_name(psection));
4830 if (NULL == name) {
4831 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4832 ok = FALSE;
4833 break;
4834 }
4836 if (pgroup == NULL) {
4837 ok = FALSE;
4838 break;
4839 }
4842 sec = NULL;
4843 }
4844 }
4845
4846 return ok;
4847}
4848
4849/**********************************************************************/
4852static bool is_on_allowed_list(const char *name, const char **list, size_t len)
4853{
4854 int i;
4855
4856 for (i = 0; i < len; i++) {
4857 if (!fc_strcasecmp(name, list[i])) {
4858 return TRUE;
4859 }
4860 }
4861 return FALSE;
4862}
4863
4864/**********************************************************************/
4868static bool load_city_name_list(struct section_file *file,
4869 struct nation_type *pnation,
4870 const char *secfile_str1,
4871 const char *secfile_str2,
4872 const char **allowed_terrains,
4873 size_t atcount)
4874{
4875 size_t dim, j;
4876 bool ok = TRUE;
4877 const char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
4879
4880 /* Each string will be of the form "<cityname> (<label>, <label>, ...)".
4881 * The cityname is just the name for this city, while each "label" matches
4882 * a terrain type for the city (or "river"), with a preceding ! to negate
4883 * it. The parentheses are optional (but necessary to have the settings,
4884 * of course). Our job is now to parse it. */
4885 for (j = 0; j < dim; j++) {
4886 size_t len = strlen(cities[j]);
4887 char city_name[len + 1], *p, *next, *end;
4888 struct nation_city *pncity;
4889
4891
4892 /* Now we wish to determine values for all of the city labels. A value
4893 * of NCP_NONE means no preference (which is necessary so that the use
4894 * of this is optional); NCP_DISLIKE means the label is negated and
4895 * NCP_LIKE means it's labelled. Mostly the parsing just involves
4896 * a lot of ugly string handling... */
4897 if ((p = strchr(city_name, '('))) {
4898 *p++ = '\0';
4899
4900 if (!(end = strchr(p, ')'))) {
4902 "\"%s\" [%s] %s: city name \"%s\" "
4903 "unmatched parenthesis.", secfile_name(file),
4905 ok = FALSE;
4906 } else {
4907 for (*end++ = '\0'; '\0' != *end; end++) {
4908 if (!fc_isspace(*end)) {
4910 "\"%s\" [%s] %s: city name \"%s\" "
4911 "contains characters after last parenthesis.",
4913 cities[j]);
4914 ok = FALSE;
4915 break;
4916 }
4917 }
4918 }
4919 }
4920
4921 /* Build the nation_city. */
4924 /* The ruleset contains a name that is too long. This shouldn't
4925 * happen - if it does, the author should get immediate feedback. */
4927 "\"%s\" [%s] %s: city name \"%s\" is too long.",
4928 secfile_name(file),
4930 ok = FALSE;
4931 city_name[MAX_LEN_CITYNAME - 1] = '\0';
4932 }
4933 pncity = nation_city_new(pnation, city_name);
4934
4935 if (NULL != p) {
4936 /* Handle the labels one at a time. */
4937 do {
4938 enum nation_city_preference prefer;
4939
4940 if ((next = strchr(p, ','))) {
4941 *next = '\0';
4942 }
4944
4945 /* The ! is used to mark a negative, which is recorded with
4946 * NCP_DISLIKE. Otherwise we use a NCP_LIKE.
4947 */
4948 if (*p == '!') {
4949 p++;
4950 prefer = NCP_DISLIKE;
4951 } else {
4952 prefer = NCP_LIKE;
4953 }
4954
4955 if (0 == fc_strcasecmp(p, "river")) {
4957 && !is_on_allowed_list(p,
4960 "\"%s\" [%s] %s: city \"%s\" "
4961 "has terrain hint \"%s\" not in allowed_terrains.",
4963 city_name, p);
4964 ok = FALSE;
4965 } else {
4967 }
4968 } else {
4969 const struct terrain *pterrain = terrain_by_rule_name(p);
4970
4971 if (NULL == pterrain) {
4972 /* Try with removing frequent trailing 's'. */
4973 size_t l = strlen(p);
4974
4975 if (0 < l && 's' == fc_tolower(p[l - 1])) {
4976 char saved = p[l - 1];
4977
4978 p[l - 1] = '\0';
4979 pterrain = terrain_by_rule_name(p);
4980 if (pterrain == NULL) {
4981 /* Didn't help, restore for later allowed_terrains check */
4982 p[l - 1] = saved;
4983 }
4984 }
4985 }
4986
4987 /* Nationset may have been devised with a specific set of terrains
4988 * in mind which don't quite match this ruleset, in which case we
4989 * (a) quietly ignore any hints mentioned that don't happen to be in
4990 * the current ruleset, (b) enforce that terrains mentioned by nations
4991 * must be on the list */
4992 if (pterrain != NULL && game.server.ruledit.allowed_terrains != NULL) {
4993 if (!is_on_allowed_list(p,
4995 /* Terrain exists, but not intended for these nations */
4997 "\"%s\" [%s] %s: city \"%s\" "
4998 "has terrain hint \"%s\" not in allowed_terrains.",
5000 city_name, p);
5001 ok = FALSE;
5002 break;
5003 }
5004 } else if (!pterrain) {
5005 /* Terrain doesn't exist; only complain if it's not on any list */
5007 || !is_on_allowed_list(p,
5010 "\"%s\" [%s] %s: city \"%s\" "
5011 "has unknown terrain hint \"%s\".",
5013 city_name, p);
5014 ok = FALSE;
5015 break;
5016 }
5017 }
5018 if (NULL != pterrain) {
5019 nation_city_set_terrain_preference(pncity, pterrain, prefer);
5020 }
5021 }
5022
5023 p = next ? next + 1 : NULL;
5024 } while (NULL != p && '\0' != *p);
5025 }
5026 }
5027
5028 if (NULL != cities) {
5029 free(cities);
5030 }
5031
5032 return ok;
5033}
5034
5035/**********************************************************************/
5038static bool load_ruleset_nations(struct section_file *file,
5039 struct rscompat_info *compat)
5040{
5041 struct government *gov;
5042 int j;
5043 size_t dim;
5044 char temp_name[MAX_LEN_NAME];
5045 const char **vec;
5046 const char *name, *bad_leader;
5047 const char *sval;
5048 int default_set;
5049 const char *filename = secfile_name(file);
5050 struct section_list *sec = NULL;
5051 enum trait tr;
5052 bool ok = TRUE;
5053
5054 name = secfile_lookup_str_default(file, NULL, "ruledit.nationlist");
5055 if (name != NULL) {
5057 }
5059 "ruledit.embedded_nations");
5060
5061 if (vec != NULL) {
5062 /* Copy to persistent vector */
5065
5066 for (j = 0; j < game.server.ruledit.embedded_nations_count; j++) {
5068 }
5069
5070 free(vec);
5071 }
5072
5074
5075 ruleset_load_traits(game.server.default_traits, file, "default_traits", "");
5076 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5077 if (game.server.default_traits[tr].min < 0) {
5079 }
5080 if (game.server.default_traits[tr].max < 0) {
5082 }
5083 if (game.server.default_traits[tr].fixed < 0) {
5085
5086 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5088 }
5091 "Default values for trait %s not sane.",
5092 trait_name(tr));
5093 ok = FALSE;
5094 break;
5095 }
5096 }
5097
5098 if (ok) {
5100 "compatibility.allowed_govs");
5101 if (vec != NULL) {
5102 /* Copy to persistent vector */
5104 = fc_malloc(game.server.ruledit.ag_count * sizeof(char *));
5106 (const char **)game.server.ruledit.nc_agovs;
5107
5108 for (j = 0; j < game.server.ruledit.ag_count; j++) {
5110 }
5111
5112 free(vec);
5113 }
5114
5116 "compatibility.allowed_terrains");
5117 if (vec != NULL) {
5118 /* Copy to persistent vector */
5120 = fc_malloc(game.server.ruledit.at_count * sizeof(char *));
5122 (const char **)game.server.ruledit.nc_aterrs;
5123
5124 for (j = 0; j < game.server.ruledit.at_count; j++) {
5126 }
5127
5128 free(vec);
5129 }
5130
5132 "compatibility.allowed_styles");
5133 if (vec != NULL) {
5134 /* Copy to persistent vector */
5136 = fc_malloc(game.server.ruledit.as_count * sizeof(char *));
5138 (const char **)game.server.ruledit.nc_astyles;
5139
5140 for (j = 0; j < game.server.ruledit.as_count; j++) {
5142 }
5143
5144 free(vec);
5145 }
5146
5148 "compatibility.default_government");
5149 /* We deliberately don't check this against allowed_govs. It's only
5150 * specified once so not vulnerable to typos, and may usefully be set in
5151 * a specific ruleset to a gov not explicitly known by the nation set. */
5152 if (sval != NULL) {
5154 if (game.default_government == NULL) {
5156 "Tried to set unknown government type \"%s\" as default_government!",
5157 sval);
5158 ok = FALSE;
5159 } else {
5162 }
5163 }
5164 }
5165
5166 if (ok) {
5168 if (sec != NULL) {
5170
5171 section_list_iterate(sec, psection) {
5172 const char *set_name, *set_rule_name, *set_description;
5173
5174 set_name = secfile_lookup_str(file, "%s.name", section_name(psection));
5176 secfile_lookup_str(file, "%s.rule_name", section_name(psection));
5177 set_description = secfile_lookup_str_default(file, "", "%s.description",
5178 section_name(psection));
5179 if (NULL == set_name || NULL == set_rule_name) {
5180 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5181 ok = FALSE;
5182 break;
5183 }
5185 ok = FALSE;
5186 break;
5187 }
5190 sec = NULL;
5191 } else {
5193 "At least one nation set [" NATION_SET_SECTION_PREFIX "_*] "
5194 "must be defined.");
5195 ok = FALSE;
5196 }
5197 }
5198
5199 if (ok) {
5200 /* Default set that every nation is a member of. */
5202 "compatibility.default_nationset");
5203 if (sval != NULL) {
5205 if (pset != NULL) {
5207 } else {
5209 "Unknown default_nationset \"%s\".", sval);
5210 ok = FALSE;
5211 }
5212 } else if (nation_set_count() == 1) {
5213 /* If there's only one set defined, every nation is implicitly a
5214 * member of that set. */
5215 default_set = 0;
5216 } else {
5217 /* No default nation set; every nation must explicitly specify at
5218 * least one set to be a member of. */
5219 default_set = -1;
5220 }
5221 }
5222
5223 if (ok) {
5225 if (sec) {
5226 section_list_iterate(sec, psection) {
5227 struct nation_group *pgroup;
5228 bool hidden;
5229
5230 name = secfile_lookup_str(file, "%s.name", section_name(psection));
5232 if (pgroup == NULL) {
5233 ok = FALSE;
5234 break;
5235 }
5236
5237 hidden = secfile_lookup_bool_default(file, FALSE, "%s.hidden",
5238 section_name(psection));
5240
5241 if (!secfile_lookup_int(file, &j, "%s.match", section_name(psection))) {
5242 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5243 ok = FALSE;
5244 break;
5245 }
5249 sec = NULL;
5250 }
5251 }
5252
5253 if (ok) {
5255 nations_iterate(pnation) {
5256 struct nation_type *pconflict;
5257 const int i = nation_index(pnation);
5258 char tmp[200] = "\0";
5259 const char *barb_type;
5260 const char *sec_name = section_name(section_list_get(sec, i));
5261 const char *legend;
5262
5263 /* Nation sets and groups. */
5264 if (default_set >= 0) {
5265 nation_set_list_append(pnation->sets,
5267 }
5268 vec = secfile_lookup_str_vec(file, &dim, "%s.groups", sec_name);
5269 for (j = 0; j < dim; j++) {
5270 struct nation_set *pset = nation_set_by_rule_name(vec[j]);
5272
5273 fc_assert(pset == NULL || pgroup == NULL);
5274
5275 if (NULL != pset) {
5276 nation_set_list_append(pnation->sets, pset);
5277 } else if (NULL != pgroup) {
5278 nation_group_list_append(pnation->groups, pgroup);
5279 } else {
5280 /* For nation authors, this would probably be considered an error.
5281 * But it can happen normally. The civ1 compatibility ruleset only
5282 * uses the nations that were in civ1, so not all of the links will
5283 * exist. */
5284 log_verbose("Nation %s: Unknown set/group \"%s\".",
5285 nation_rule_name(pnation), vec[j]);
5286 }
5287 }
5288 if (NULL != vec) {
5289 free(vec);
5290 }
5291 if (nation_set_list_size(pnation->sets) < 1) {
5293 "Nation %s is not a member of any nation set",
5294 nation_rule_name(pnation));
5295 ok = FALSE;
5296 break;
5297 }
5298
5299 /* Nation conflicts. */
5300 vec = secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec_name);
5301 for (j = 0; j < dim; j++) {
5303
5304 if (pnation == pconflict) {
5306 "Nation %s conflicts with itself",
5307 nation_rule_name(pnation));
5308 ok = FALSE;
5309 break;
5310 } else if (NULL != pconflict) {
5311 nation_list_append(pnation->server.conflicts_with, pconflict);
5312 } else {
5313 /* For nation authors, this would probably be considered an error.
5314 * But it can happen normally. The civ1 compatibility ruleset only
5315 * uses the nations that were in civ1, so not all of the links will
5316 * exist. */
5317 log_verbose("Nation %s: conflicts_with nation \"%s\" is unknown.",
5318 nation_rule_name(pnation), vec[j]);
5319 }
5320 }
5321 if (NULL != vec) {
5322 free(vec);
5323 }
5324 if (!ok) {
5325 break;
5326 }
5327
5328 /* Nation leaders. */
5329 for (j = 0; j < MAX_NUM_LEADERS; j++) {
5330 const char *sexstr;
5331 sex_t sex;
5332 bool is_male = FALSE;
5333
5334 name = secfile_lookup_str(file, "%s.leaders%d.name", sec_name, j);
5335 if (NULL == name) {
5336 /* No more to read. */
5337 break;
5338 }
5339
5340 if (check_name(name)) {
5341 /* The ruleset contains a name that is too long. This shouldn't
5342 * happen - if it does, the author should get immediate feedback */
5345 "Nation %s: leader name \"%s\" is too long.",
5346 nation_rule_name(pnation), name);
5347 ok = FALSE;
5348 break;
5349 }
5350
5351 sexstr = secfile_lookup_str(file, "%s.leaders%d.sex", sec_name, j);
5352 if (NULL == sexstr) {
5354 "Nation %s: leader \"%s\": %s.",
5355 nation_rule_name(pnation), name, secfile_error());
5356 ok = FALSE;
5357 break;
5358 }
5359
5361
5362 switch (sex) {
5363 case SEX_MALE:
5364 is_male = TRUE;
5365 break;
5366 case SEX_FEMALE:
5367 is_male = FALSE;
5368 break;
5369 case SEX_UNKNOWN:
5371 "Nation %s: leader \"%s\" has unsupported "
5372 "sex variant \"%s\".",
5373 nation_rule_name(pnation), name, sexstr);
5374 ok = FALSE;
5375 break;
5376 }
5377
5378 if (ok) {
5379 (void) nation_leader_new(pnation, name, is_male);
5380 }
5381 }
5382 if (!ok) {
5383 break;
5384 }
5385
5386 /* Check the number of leaders. */
5387 if (MAX_NUM_LEADERS == j) {
5388 /* Too much leaders, get the real number defined in the ruleset. */
5389 while (NULL != secfile_entry_lookup(file, "%s.leaders%d.name",
5390 sec_name, j)) {
5391 j++;
5392 }
5394 "Nation %s: Too many leaders; max is %d",
5396 ok = FALSE;
5397 break;
5398 } else if (0 == j) {
5400 "Nation %s: no leaders; at least one is required.",
5401 nation_rule_name(pnation));
5402 ok = FALSE;
5403 break;
5404 }
5405
5406 /* Check if leader name is not already defined in this nation. */
5407 if ((bad_leader = check_leader_names(pnation))) {
5409 "Nation %s: leader \"%s\" defined more than once.",
5410 nation_rule_name(pnation), bad_leader);
5411 ok = FALSE;
5412 break;
5413 }
5414
5415 /* Nation player color preference, if any */
5416 fc_assert_ret_val(pnation->server.rgb == NULL, FALSE);
5417 (void) rgbcolor_load(file, &pnation->server.rgb, "%s.color", sec_name);
5418
5419 /* Load nation traits */
5420 ruleset_load_traits(pnation->server.traits, file, sec_name, "trait_");
5421 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5422 bool server_traits_used = TRUE;
5423
5424 if (pnation->server.traits[tr].min < 0) {
5425 pnation->server.traits[tr].min = game.server.default_traits[tr].min;
5426 } else {
5428 }
5429 if (pnation->server.traits[tr].max < 0) {
5430 pnation->server.traits[tr].max = game.server.default_traits[tr].max;
5431 } else {
5433 }
5434 if (pnation->server.traits[tr].fixed < 0) {
5435 if (server_traits_used) {
5436 pnation->server.traits[tr].fixed = game.server.default_traits[tr].fixed;
5437 } else {
5438 int diff = pnation->server.traits[tr].max - pnation->server.traits[tr].min;
5439
5440 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5441 pnation->server.traits[tr].fixed = diff / 2 + pnation->server.traits[tr].min;
5442 }
5443 }
5444 if (pnation->server.traits[tr].max < pnation->server.traits[tr].min) {
5446 "%s values for trait %s not sane.",
5447 nation_rule_name(pnation), trait_name(tr));
5448 ok = FALSE;
5449 break;
5450 }
5451 }
5452
5453 if (!ok) {
5454 break;
5455 }
5456
5457 pnation->is_playable =
5458 secfile_lookup_bool_default(file, TRUE, "%s.is_playable", sec_name);
5459
5460 /* Check barbarian type. Default is "None" meaning not a barbarian */
5461 barb_type = secfile_lookup_str_default(file, "None",
5462 "%s.barbarian_type", sec_name);
5463 pnation->barb_type = barbarian_type_by_name(barb_type, fc_strcasecmp);
5464 if (!barbarian_type_is_valid(pnation->barb_type)) {
5466 "Nation %s, barbarian_type is invalid (\"%s\")",
5467 nation_rule_name(pnation), barb_type);
5468 ok = FALSE;
5469 break;
5470 }
5471
5472 if (pnation->barb_type != NOT_A_BARBARIAN
5473 && pnation->is_playable) {
5474 /* We can't allow players to use barbarian nations, barbarians
5475 * may run out of nations */
5477 "Nation %s marked both barbarian and playable.",
5478 nation_rule_name(pnation));
5479 ok = FALSE;
5480 break;
5481 }
5482
5483 /* Flags */
5484 sz_strlcpy(pnation->flag_graphic_str,
5485 secfile_lookup_str_default(file, "-", "%s.flag", sec_name));
5486 sz_strlcpy(pnation->flag_graphic_alt,
5488 "%s.flag_alt", sec_name));
5489
5490 /* Ruler titles */
5491 for (j = 0;; j++) {
5492 const char *male, *female;
5493
5495 "%s.ruler_titles%d.government",
5496 sec_name, j);
5497 if (NULL == name) {
5498 /* End of the list of ruler titles. */
5499 break;
5500 }
5501
5502 /* NB: even if the government doesn't exist, we load the entries for
5503 * the ruler titles to avoid warnings about unused entries. */
5504 male = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
5505 sec_name, j);
5506 female = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
5507 sec_name, j);
5509
5510 /* Nationset may have been devised with a specific set of govs in
5511 * mind which don't quite match this ruleset, in which case we
5512 * (a) quietly ignore any govs mentioned that don't happen to be in
5513 * the current ruleset, (b) enforce that govs mentioned by nations
5514 * must be on the list */
5515 if (gov != NULL && game.server.ruledit.allowed_govs != NULL) {
5519 /* Gov exists, but not intended for these nations */
5520 gov = NULL;
5522 "Nation %s: government \"%s\" not in allowed_govs.",
5523 nation_rule_name(pnation), name);
5524 ok = FALSE;
5525 break;
5526 }
5527 } else if (!gov) {
5528 /* Gov doesn't exist; only complain if it's not on any list */
5534 "Nation %s: government \"%s\" not found.",
5535 nation_rule_name(pnation), name);
5536 ok = FALSE;
5537 break;
5538 }
5539 }
5540 if (NULL != male && NULL != female) {
5541 if (gov) {
5542 (void) government_ruler_title_new(gov, pnation, male, female);
5543 }
5544 } else {
5546 ok = FALSE;
5547 break;
5548 }
5549 }
5550 if (!ok) {
5551 break;
5552 }
5553
5554 /* City styles */
5555 name = secfile_lookup_str(file, "%s.style", sec_name);
5556 if (!name) {
5558 ok = FALSE;
5559 break;
5560 }
5561 pnation->style = style_by_rule_name(name);
5562 if (pnation->style == NULL) {
5568 "Nation %s: Illegal style \"%s\"",
5569 nation_rule_name(pnation), name);
5570 ok = FALSE;
5571 break;
5572 } else {
5573 log_verbose("Nation %s: style \"%s\" not supported in this "
5574 "ruleset; using default.",
5575 nation_rule_name(pnation), name);
5576 pnation->style = style_by_number(0);
5577 }
5578 }
5579
5580 /* Civilwar nations */
5581 vec = secfile_lookup_str_vec(file, &dim,
5582 "%s.civilwar_nations", sec_name);
5583 for (j = 0; j < dim; j++) {
5585
5586 /* No test for duplicate nations is performed. If there is a duplicate
5587 * entry it will just cause that nation to have an increased
5588 * probability of being chosen. */
5589 if (pconflict == pnation) {
5591 "Nation %s is its own civil war nation",
5592 nation_rule_name(pnation));
5593 ok = FALSE;
5594 break;
5595 } else if (NULL != pconflict) {
5596 nation_list_append(pnation->server.civilwar_nations, pconflict);
5597 nation_list_append(pconflict->server.parent_nations, pnation);
5598 } else {
5599 /* For nation authors, this would probably be considered an error.
5600 * But it can happen normally. The civ1 compatibility ruleset only
5601 * uses the nations that were in civ1, so not all of the links will
5602 * exist. */
5603 log_verbose("Nation %s: civil war nation \"%s\" is unknown.",
5604 nation_rule_name(pnation), vec[j]);
5605 }
5606 }
5607 if (NULL != vec) {
5608 free(vec);
5609 }
5610 if (!ok) {
5611 break;
5612 }
5613
5614 /* Load nation specific initial items */
5615 if (!lookup_tech_list(file, sec_name, "init_techs",
5616 pnation->init_techs, filename)) {
5617 ok = FALSE;
5618 break;
5619 }
5620 if (!lookup_building_list(file, sec_name, "init_buildings",
5621 pnation->init_buildings, filename)) {
5622 ok = FALSE;
5623 break;
5624 }
5625 if (!lookup_unit_list(file, sec_name, "init_units",
5626 pnation->init_units, filename)) {
5627 ok = FALSE;
5628 break;
5629 }
5630 fc_strlcat(tmp, sec_name, 200);
5631 fc_strlcat(tmp, ".init_government", 200);
5632 if (secfile_entry_by_path(file, tmp)) {
5633 pnation->init_government = lookup_government(file, tmp, filename,
5634 NULL);
5635 /* If specified, init_government has to be in this specific ruleset,
5636 * not just allowed_govs */
5637 if (pnation->init_government == NULL) {
5638 ok = FALSE;
5639 break;
5640 }
5641 /* ...but if a list of govs has been specified, enforce that this
5642 * nation's init_government is on the list. */
5644 && !is_on_allowed_list(government_rule_name(pnation->init_government),
5648 "Nation %s: init_government \"%s\" not allowed.",
5649 nation_rule_name(pnation),
5650 government_rule_name(pnation->init_government));
5651 ok = FALSE;
5652 break;
5653 }
5654 }
5655
5656 /* Read default city names. */
5657 if (!load_city_name_list(file, pnation, sec_name, "cities",
5660 ok = FALSE;
5661 break;
5662 }
5663
5664 legend = secfile_lookup_str_default(file, "", "%s.legend", sec_name);
5665 pnation->legend = fc_strdup(legend);
5666 if (check_strlen(pnation->legend, MAX_LEN_MSG, NULL)) {
5668 "Nation %s: legend \"%s\" is too long.",
5669 nation_rule_name(pnation),
5670 pnation->legend);
5671 ok = FALSE;
5672 break;
5673 }
5674
5675 pnation->player = NULL;
5678 sec = NULL;
5679 }
5680
5681 /* Clean up on aborted load */
5682 if (sec != NULL) {
5683 fc_assert(!ok);
5685 }
5686
5687 if (ok) {
5689 }
5690
5691 if (ok) {
5692 /* Update cached number of playable nations in the current set */
5694
5695 /* Sanity checks on all sets */
5698
5699 nations_iterate(pnation) {
5700 if (nation_is_in_set(pnation, pset)) {
5701 switch (nation_barbarian_type(pnation)) {
5702 case NOT_A_BARBARIAN:
5703 if (is_nation_playable(pnation)) {
5704 num_playable++;
5705 }
5706 break;
5707 case LAND_BARBARIAN:
5709 break;
5710 case SEA_BARBARIAN:
5712 break;
5713 case ANIMAL_BARBARIAN:
5714 /* Animals are optional */
5715 break;
5718 break;
5719 default:
5721 }
5722 }
5724 if (num_playable < 1) {
5726 "Nation set \"%s\" has no playable nations. "
5727 "At least one required!", nation_set_rule_name(pset));
5728 ok = FALSE;
5729 break;
5730 }
5731 if (barb_land_count == 0 && barb_both_count == 0) {
5733 "No land barbarian nation defined in set \"%s\". "
5734 "At least one required!", nation_set_rule_name(pset));
5735 ok = FALSE;
5736 break;
5737 }
5738 if (barb_sea_count == 0 && barb_both_count == 0) {
5740 "No sea barbarian nation defined in set \"%s\". "
5741 "At least one required!", nation_set_rule_name(pset));
5742 ok = FALSE;
5743 break;
5744 }
5746 }
5747
5748 return ok;
5749}
5750
5751/**********************************************************************/
5755static bool load_style_names(struct section_file *file,
5756 struct rscompat_info *compat)
5757{
5758 bool ok = TRUE;
5759 struct section_list *sec;
5760 const char *filename = secfile_name(file);
5761
5762 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5763 return FALSE;
5764 }
5765
5766 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5767 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5768
5770 if (NULL == sec) {
5772 "No available nation styles in this ruleset!");
5773 ok = FALSE;
5774 } else {
5776
5778
5780 const int i = style_index(ps);
5781 const char *sec_name = section_name(section_list_get(sec, i));
5782
5783 ruleset_load_names(&ps->name, NULL, file, sec_name);
5785 }
5786
5788
5789 if (ok) {
5790 /* The citystyle sections: */
5791 int i = 0;
5792
5794 if (NULL != sec) {
5796 section_list_iterate(sec, style) {
5797 if (!ruleset_load_names(&city_styles[i].name, NULL, file, section_name(style))) {
5798 ok = FALSE;
5799 break;
5800 }
5801 i++;
5803
5805 } else {
5807 }
5808 }
5809
5810 return ok;
5811}
5812
5813/**********************************************************************/
5816static bool load_ruleset_styles(struct section_file *file,
5817 struct rscompat_info *compat)
5818{
5819 struct section_list *sec;
5820 int i;
5821 bool ok = TRUE;
5822
5823 /* City Styles ... */
5824
5826
5827 /* Get rest: */
5828 for (i = 0; i < game.control.num_city_styles; i++) {
5829 struct requirement_vector *reqs;
5830 const char *sec_name = section_name(section_list_get(sec, i));
5831
5832 sz_strlcpy(city_styles[i].graphic,
5833 secfile_lookup_str(file, "%s.graphic", sec_name));
5834 sz_strlcpy(city_styles[i].graphic_alt,
5835 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
5836 sz_strlcpy(city_styles[i].citizens_graphic,
5838 "%s.citizens_graphic", sec_name));
5839
5841 if (reqs == NULL) {
5842 ok = FALSE;
5843 break;
5844 }
5846 }
5847
5849
5850 if (ok) {
5852
5853 if (sec != NULL) {
5854 int musi;
5855
5858 musi = 0;
5859
5860 section_list_iterate(sec, psection) {
5861 struct requirement_vector *reqs;
5863 const char *sec_name = section_name(psection);
5864
5865 sz_strlcpy(pmus->music_peaceful,
5867 "%s.music_peaceful", sec_name));
5868 sz_strlcpy(pmus->music_combat,
5870 "%s.music_combat", sec_name));
5871
5872 reqs = lookup_req_list(file, compat, sec_name, "reqs", "Music Style");
5873 if (reqs == NULL) {
5874 ok = FALSE;
5875 break;
5876 }
5878
5879 musi++;
5881 }
5882
5884 }
5885
5886 return ok;
5887}
5888
5889/**********************************************************************/
5896 const char *uflags_path,
5897 const char *filename)
5898{
5899 /* Add each listed protected unit type flag as a !present
5900 * requirement. */
5901 if (secfile_entry_lookup(file, "%s", uflags_path)) {
5903 size_t psize;
5904 int i;
5905
5908 "%s", uflags_path);
5909
5910 if (!protecor_flag) {
5911 /* Entity exists but couldn't read it. */
5913 "\"%s\": %s: bad unit type flag list.",
5914 filename, uflags_path);
5915
5916 return FALSE;
5917 }
5918
5919 for (i = 0; i < psize; i++) {
5923 FALSE, FALSE, TRUE,
5924 protecor_flag[i]));
5925 }
5926
5928 }
5929
5930 return TRUE;
5931}
5932
5933/**********************************************************************/
5939 const char *actions_path,
5940 const char *filename)
5941{
5942 /* Read the alternative actions. */
5943 if (secfile_entry_lookup(file, "%s", actions_path)) {
5944 enum gen_action *unit_acts;
5945 size_t asize;
5946 int i;
5947
5949 "%s", actions_path);
5950
5951 if (!unit_acts) {
5952 /* Entity exists but couldn't read it. */
5954 "\"%s\": %s: bad action list",
5955 filename, actions_path);
5956
5957 return FALSE;
5958 }
5959
5960 for (i = 0; i < asize; i++) {
5961 auto_perf->alternatives[i] = unit_acts[i];
5962 }
5963
5964 free(unit_acts);
5965 }
5966
5967 return TRUE;
5968}
5969
5970/**********************************************************************/
5975 const char *item,
5976 const char *filename)
5977{
5978 char uflags_path[100];
5979 char action_path[100];
5980
5982 "missing_unit_upkeep.%s_protected", item);
5984 "missing_unit_upkeep.%s_unit_act", item);
5985
5987 filename)
5989 filename));
5990}
5991
5992/**********************************************************************/
5995static bool load_ruleset_cities(struct section_file *file,
5996 struct rscompat_info *compat)
5997{
5998 const char *filename = secfile_name(file);
5999 const char *item;
6000 struct section_list *sec;
6001 bool ok = TRUE;
6002
6003 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6004 return FALSE;
6005 }
6006
6007 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6008 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6009
6010 /* Specialist options */
6012 if (section_list_size(sec) >= SP_MAX) {
6014 "\"%s\": Too many specialists (%d, max %d).",
6015 filename, section_list_size(sec), SP_MAX);
6016 ok = FALSE;
6017 }
6018
6019 if (ok) {
6020 int i = 0;
6021 const char *tag;
6022
6024
6025 section_list_iterate(sec, psection) {
6026 struct specialist *s = specialist_by_number(i);
6027 struct requirement_vector *reqs;
6028 const char *sec_name = section_name(psection);
6029
6030 if (!ruleset_load_names(&s->name, NULL, file, sec_name)) {
6031 ok = FALSE;
6032 break;
6033 }
6034
6036 "%s.short_name", sec_name);
6038
6039 tag = secfile_lookup_str(file, "%s.graphic", sec_name);
6040 if (tag == NULL) {
6042 "\"%s\": No graphic tag for specialist at %s.",
6043 filename, sec_name);
6044 ok = FALSE;
6045 break;
6046 }
6047 sz_strlcpy(s->graphic_str, tag);
6050 "%s.graphic_alt", sec_name));
6051
6053 if (reqs == NULL) {
6054 ok = FALSE;
6055 break;
6056 }
6058
6059 s->helptext = lookup_strvec(file, sec_name, "helptext");
6060
6061 if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
6063 }
6064 i++;
6066 }
6067
6068 if (ok && DEFAULT_SPECIALIST == -1) {
6070 "\"%s\": must give a min_size of 0 for at least one "
6071 "specialist type.", filename);
6072 ok = FALSE;
6073 }
6075 sec = NULL;
6076
6077 if (ok) {
6078 /* City Parameters */
6079
6082 "parameters.celebrate_size_limit");
6084 secfile_lookup_int_default(file, GAME_DEFAULT_ADDTOSIZE, "parameters.add_to_size_limit");
6087 "parameters.angry_citizens");
6088
6090 secfile_lookup_bool_default(file, GAME_DEFAULT_CHANGABLE_TAX, "parameters.changable_tax");
6092 secfile_lookup_int_default(file, 0, "parameters.forced_science");
6094 secfile_lookup_int_default(file, 100, "parameters.forced_luxury");
6096 secfile_lookup_int_default(file, 0, "parameters.forced_gold");
6098 + game.info.forced_gold != 100) {
6100 "\"%s\": Forced taxes do not add up in ruleset!",
6101 filename);
6102 ok = FALSE;
6103 }
6104 }
6105
6106 if (ok) {
6108
6109 /* civ1 & 2 didn't reveal tiles */
6112 "parameters.vision_reveal_tiles");
6113
6115 secfile_lookup_int_default(file, 1, "parameters.pop_report_zeroes");
6116
6117 /* Citizens configuration. */
6120 "citizen.nationality");
6121
6122 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
6123 /* Same as old hardcoded behavior */
6125 }
6128 "citizen.ubuilder_nationality");
6131 "citizen.convert_speed");
6133 secfile_lookup_int_default(file, 0, "citizen.partisans_pct");
6135 secfile_lookup_int_default(file, 0, "citizen.conquest_convert_pct");
6136 }
6137
6138 if (ok) {
6139 /* Missing unit upkeep. */
6141
6142 /* Can't pay food upkeep! */
6144 auto_perf->cause = AAPC_UNIT_UPKEEP;
6145
6146 /* This is about food upkeep. */
6148 req_from_str("OutputType", "Local",
6149 FALSE, TRUE, TRUE,
6150 "Food"));
6151
6152 /* Internally represented as an action auto performer rule. */
6153 if (!load_muuk_as_action_auto(file, auto_perf, "food", filename)) {
6154 ok = FALSE;
6155 }
6156
6159 "missing_unit_upkeep.food_wipe");
6160
6161 /* Can't pay gold upkeep! */
6163 auto_perf->cause = AAPC_UNIT_UPKEEP;
6164
6165 /* This is about gold upkeep. */
6167 req_from_str("OutputType", "Local",
6168 FALSE, TRUE, TRUE,
6169 "Gold"));
6170
6171 /* Internally represented as an action auto performer rule. */
6172 if (!load_muuk_as_action_auto(file, auto_perf, "gold", filename)) {
6173 ok = FALSE;
6174 }
6175
6178 "missing_unit_upkeep.gold_wipe");
6179
6180 /* Can't pay shield upkeep! */
6182 auto_perf->cause = AAPC_UNIT_UPKEEP;
6183
6184 /* This is about shield upkeep. */
6186 req_from_str("OutputType", "Local",
6187 FALSE, TRUE, TRUE,
6188 "Shield"));
6189
6190 /* Internally represented as an action auto performer rule. */
6191 if (!load_muuk_as_action_auto(file, auto_perf, "shield", filename)) {
6192 ok = FALSE;
6193 }
6194
6197 "missing_unit_upkeep.shield_wipe");
6198 }
6199
6200 if (ok) {
6202 }
6203
6204 return ok;
6205}
6206
6207/**********************************************************************/
6210static bool load_ruleset_effects(struct section_file *file,
6211 struct rscompat_info *compat)
6212{
6213 struct section_list *sec;
6214 const char *filename;
6215 bool ok = TRUE;
6216
6217 filename = secfile_name(file);
6218
6219 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6220 return FALSE;
6221 }
6222
6223 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6224 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6225
6227
6228 if (sec != NULL) {
6229 section_list_iterate(sec, psection) {
6230 const char *sec_name = section_name(psection);
6231 enum effect_type main_type;
6232 enum effect_type ai_valued_as;
6233 const char *type;
6234
6235 type = secfile_lookup_str(file, "%s.type", sec_name);
6236 if (type == NULL) {
6238 "\"%s\" [%s] missing effect type.",
6239 filename, sec_name);
6240 ok = FALSE;
6241 break;
6242 }
6246 "\"%s\" [%s] lists unknown effect type \"%s\".",
6247 filename, sec_name, type);
6248 ok = FALSE;
6249 break;
6250 }
6251 if (!is_user_effect(main_type)) {
6253 "\"%s\" [%s] type \"%s\" is not an user effect.",
6254 filename, sec_name, type);
6255 ok = FALSE;
6256 break;
6257 }
6258
6259 type = secfile_lookup_str(file, "%s.ai_valued_as", sec_name);
6260 if (type == NULL) {
6262 "\"%s\" [%s] missing ai_valued_as.",
6263 filename, sec_name);
6264 ok = FALSE;
6265 break;
6266 }
6270 "\"%s\" [%s] lists unknown ai_valued_as \"%s\".",
6271 filename, sec_name, type);
6272 ok = FALSE;
6273 break;
6274 }
6277 "\"%s\" [%s] ai_valued_as \"%s\" is an user effect.",
6278 filename, sec_name, type);
6279 ok = FALSE;
6280 break;
6281 }
6282
6284 /* It has been set already! */
6286 "\"%s\" [%s] Duplicate \"%s\" entry.",
6287 filename, sec_name, type);
6288 ok = FALSE;
6289 break;
6290 }
6291
6294
6296 }
6297
6298 /* Parse effects and add them to the effects ruleset cache. */
6300 section_list_iterate(sec, psection) {
6301 enum effect_type eff;
6302 int value;
6303 struct multiplier *pmul;
6304 struct effect *peffect;
6305 const char *sec_name = section_name(psection);
6306 struct requirement_vector *reqs;
6307 const char *type;
6308 const char *comment;
6309
6310 type = secfile_lookup_str(file, "%s.type", sec_name);
6311
6312 if (type == NULL) {
6314 "\"%s\" [%s] missing effect type.",
6315 filename, sec_name);
6316 ok = FALSE;
6317 break;
6318 }
6319
6321 if (!effect_type_is_valid(eff)) {
6323 "\"%s\" [%s] lists unknown effect type \"%s\".",
6324 filename, sec_name, type);
6325 ok = FALSE;
6326 break;
6327 }
6328
6329 value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
6330
6331 {
6332 const char *multiplier_name
6333 = secfile_lookup_str(file, "%s.multiplier", sec_name);
6334
6335 if (multiplier_name) {
6337 if (!pmul) {
6339 "\"%s\" [%s] has unknown multiplier \"%s\".",
6340 filename, sec_name, multiplier_name);
6341 ok = FALSE;
6342 break;
6343 }
6344 } else {
6345 pmul = NULL;
6346 }
6347 }
6348
6349 peffect = effect_new(eff, value, pmul);
6350
6351 reqs = lookup_req_list(file, compat, sec_name, "reqs", type);
6352 if (reqs == NULL) {
6353 ok = FALSE;
6354 break;
6355 }
6356
6360
6361 comment = secfile_lookup_str_default(file, NULL, "%s.comment", sec_name);
6362
6363 if (comment != NULL) {
6364 peffect->rulesave.comment = fc_strdup(comment);
6365 }
6366
6369
6370 if (ok) {
6372 }
6373
6374 return ok;
6375}
6376
6377/**********************************************************************/
6380static int secfile_lookup_int_default_min_max(struct section_file *file,
6381 int def, int min, int max,
6382 const char *path, ...)
6385 int def, int min, int max,
6386 const char *path, ...)
6387{
6388 char fullpath[256];
6389 int ival;
6390 va_list args;
6391
6392 va_start(args, path);
6393 fc_vsnprintf(fullpath, sizeof(fullpath), path, args);
6394 va_end(args);
6395
6396 if (!secfile_lookup_int(file, &ival, "%s", fullpath)) {
6397 ival = def;
6398 }
6399
6400 if (ival < min) {
6402 "\"%s\" should be in the interval [%d, %d] "
6403 "but is %d; using the minimal value.",
6404 fullpath, min, max, ival);
6405 ival = min;
6406 }
6407
6408 if (ival > max) {
6410 "\"%s\" should be in the interval [%d, %d] "
6411 "but is %d; using the maximal value.",
6412 fullpath, min, max, ival);
6413 ival = max;
6414 }
6415
6416 return ival;
6417}
6418
6419/**********************************************************************/
6422static bool load_action_ui_name(struct section_file *file, int act,
6423 const char *entry_name,
6424 const char *compat_name)
6425{
6426 const char *text;
6427 const char *def = action_ui_name_default(act);
6428
6429 if (compat_name != NULL) {
6430 def = secfile_lookup_str_default(file, def,
6431 "actions.%s", compat_name);
6432 }
6433
6434 text = secfile_lookup_str_default(file, def,
6435 "actions.%s", entry_name);
6436 sz_strlcpy(action_by_number(act)->ui_name, text);
6437
6438 return TRUE;
6439}
6440
6441/**********************************************************************/
6444static bool load_action_range_max(struct section_file *file, action_id act)
6445{
6446 struct action *paction = action_by_number(act);
6447 const char *vname = action_max_range_ruleset_var_name(act);
6448
6449 if (vname != NULL) {
6450 struct entry *pentry;
6451 int max_range;
6452
6453 pentry = secfile_entry_lookup(file, "actions.%s", vname);
6454
6455 if (pentry == NULL) {
6457 } else {
6458 const char *custom;
6459
6462 /* max_range already assigned */
6463 } else if (entry_type_get(pentry) == ENTRY_STR
6467 } else {
6468 ruleset_error(NULL, LOG_ERROR, "Bad actions.%s",
6471
6472 return FALSE;
6473 }
6474 }
6475
6477 }
6478
6479 return TRUE;
6480}
6481
6482/**********************************************************************/
6485static bool load_action_range(struct section_file *file, action_id act)
6486{
6487 struct action *paction = action_by_number(act);
6488 const char *vname;
6489
6490 if (!load_action_range_max(file, act)) {
6491 return FALSE;
6492 }
6493
6495 if (vname != NULL) {
6496 /* Min range can be loaded from the ruleset. */
6500 "actions.%s",
6501 vname);
6502 }
6503
6504 return TRUE;
6505}
6506
6507/**********************************************************************/
6510static bool load_action_kind(struct section_file *file, action_id act)
6511{
6512 struct action *paction = action_by_number(act);
6513
6515 /* Target kind can't be loaded from the ruleset. */
6516 }
6517
6521 paction->result),
6523 "actions.%s",
6525
6526 return TRUE;
6527}
6528
6529/**********************************************************************/
6533 action_id act)
6534{
6536 /* Actor consumption can be loaded from the ruleset. */
6539 file, RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS, "actions.%s",
6541 }
6542
6543 return TRUE;
6544}
6545
6546/**********************************************************************/
6550 const char *filename,
6551 struct action *paction)
6552{
6554 /* Action blocking can be loaded from the ruleset. */
6555
6556 char fullpath[1024];
6557
6558 fc_snprintf(fullpath, sizeof(fullpath), "actions.%s",
6560
6561 if (secfile_entry_by_path(file, fullpath)) {
6563 size_t asize;
6564 int j;
6565
6568
6569 if (!blocking_actions) {
6570 /* Entity exists but couldn't read it. */
6572 "\"%s\": %s: bad action list",
6573 filename, fullpath);
6574
6575 return FALSE;
6576 }
6577
6578 for (j = 0; j < asize; j++) {
6579 BV_SET(paction->blocked_by, blocking_actions[j]);
6580 }
6581
6583 }
6584 }
6585
6586 return TRUE;
6587}
6588
6589/**********************************************************************/
6594 const char *filename,
6595 int performer_slot,
6596 struct action *paction)
6597{
6599 char action_list_path[100];
6600
6602 /* Not relevant. */
6603 return TRUE;
6604 }
6605
6607 auto_perf->cause = AAPC_POST_ACTION;
6608
6609 /* Limit auto performer to this action. */
6612 FALSE, TRUE, TRUE,
6613 paction->id));
6614
6615 /* Load the list of actions. */
6617 "actions.%s",
6620 action_list_path, filename)) {
6621 return FALSE;
6622 }
6623
6624 return TRUE;
6625}
6626
6627/**********************************************************************/
6630static bool lookup_bv_actions(struct section_file *file,
6631 const char *filename,
6632 bv_actions *target,
6633 const char *path)
6634{
6635 if (secfile_entry_by_path(file, path)) {
6637 size_t asize;
6638 int j;
6639
6641 "%s", path);
6642
6643 if (!listed_actions) {
6644 /* Entity exists but couldn't read it. */
6645 ruleset_error(NULL, LOG_ERROR, "\"%s\": %s: bad action list",
6646 filename, path);
6647
6648 return FALSE;
6649 }
6650
6651 for (j = 0; j < asize; j++) {
6652 BV_SET(*target, listed_actions[j]);
6653 }
6654
6656 }
6657
6658 return TRUE;
6659}
6660
6661/**********************************************************************/
6664static bool load_ruleset_game(struct section_file *file, bool act,
6665 struct rscompat_info *compat)
6666{
6667 const char *sval, **svec;
6668 const char *filename;
6669 int *food_ini;
6670 int i;
6671 size_t teams;
6672 const char *pref_text;
6673 size_t gni_tmp;
6674 struct section_list *sec;
6675 size_t nval;
6676 const char *name;
6677 bool ok = TRUE;
6678
6679 if (file == NULL) {
6680 return FALSE;
6681 }
6682 filename = secfile_name(file);
6683
6684 name = secfile_lookup_str_default(file, NULL, "ruledit.description_file");
6685 if (name != NULL) {
6687 }
6688
6689 /* Section: tileset */
6690 pref_text = secfile_lookup_str_default(file, "", "tileset.prefered");
6691 if (pref_text[0] != '\0') {
6692 log_deprecation("Entry tileset.prefered in game.ruleset."
6693 " Use correct spelling tileset.preferred instead");
6694 }
6695 pref_text = secfile_lookup_str_default(file, pref_text, "tileset.preferred");
6696 if (pref_text[0] != '\0') {
6697 /* There was tileset suggestion */
6699 } else {
6700 /* No tileset suggestions */
6701 game.control.preferred_tileset[0] = '\0';
6702 }
6703
6704 /* Section: soundset */
6705 pref_text = secfile_lookup_str_default(file, "", "soundset.prefered");
6706 if (pref_text[0] != '\0') {
6707 log_deprecation("Entry soundset.prefered in game.ruleset."
6708 " Use correct spelling soundset.preferred instead");
6709 }
6710 pref_text = secfile_lookup_str_default(file, pref_text, "soundset.preferred");
6711 if (pref_text[0] != '\0') {
6712 /* There was soundset suggestion */
6714 } else {
6715 /* No soundset suggestions */
6717 }
6718
6719 /* Section: musicset */
6720 pref_text = secfile_lookup_str_default(file, "", "musicset.prefered");
6721 if (pref_text[0] != '\0') {
6722 log_deprecation("Entry musicset.prefered in game.ruleset."
6723 " Use correct spelling musicset.preferred instead");
6724 }
6725 pref_text = secfile_lookup_str_default(file, pref_text, "musicset.preferred");
6726 if (pref_text[0] != '\0') {
6727 /* There was musicset suggestion */
6729 } else {
6730 /* No musicset suggestions */
6732 }
6733
6734 /* Section: about */
6735 pref_text = secfile_lookup_str(file, "about.name");
6736 /* Ruleset/modpack name found */
6738
6739 pref_text = secfile_lookup_str_default(file, "", "about.version");
6740 if (pref_text[0] != '\0') {
6741 /* Ruleset/modpack version found */
6743 } else {
6744 /* No version information */
6745 game.control.version[0] = '\0';
6746 }
6747
6748 pref_text = secfile_lookup_str_default(file, "", "about.alt_dir");
6749 if (pref_text[0] != '\0') {
6750 /* Alt directory definition found. */
6752 } else {
6753 /* No alt directory information */
6754 game.control.alt_dir[0] = '\0';
6755 }
6756
6757 pref_text = secfile_lookup_str_default(file, "", "about.summary");
6758 if (pref_text[0] != '\0') {
6759 int len;
6760
6761 /* Ruleset/modpack summary found */
6762 len = strlen(pref_text);
6765 } else {
6766 /* No summary */
6767 if (game.ruleset_summary != NULL) {
6770 }
6771 }
6772
6773 pref_text = secfile_lookup_str_default(file, "", "about.description");
6774 if (pref_text[0] != '\0') {
6775 int len;
6776
6777 /* Ruleset/modpack description found */
6778 len = strlen(pref_text);
6782 } else {
6783 /* No description */
6784 if (game.ruleset_description != NULL) {
6787 }
6789 }
6790
6791 pref_text = secfile_lookup_str_default(file, "", "about.capabilities");
6792 if (pref_text[0] != '\0') {
6793 int len = strlen(pref_text);
6794
6797 } else {
6799 game.ruleset_capabilities[0] = '\0';
6800 }
6801
6802 /* Section: options */
6803 if (!lookup_tech_list(file, "options", "global_init_techs",
6804 game.rgame.global_init_techs, filename)) {
6805 ok = FALSE;
6806 }
6807
6808 if (ok) {
6809 if (!lookup_building_list(file, "options", "global_init_buildings",
6810 game.rgame.global_init_buildings, filename)) {
6811 ok = FALSE;
6812 }
6813 }
6814
6815 if (ok) {
6816 const char **slist;
6817 int j;
6818
6820 "options.popup_tech_help");
6821
6822 /* section: civstyle */
6825 "civstyle.base_pollution");
6826
6828
6829 slist = secfile_lookup_str_vec(file, &nval, "civstyle.gameloss_style");
6830 for (j = 0; j < nval; j++) {
6831 enum gameloss_style style;
6832
6833 sval = slist[j];
6834 if (strcmp(sval, "") == 0) {
6835 continue;
6836 }
6838 if (!gameloss_style_is_valid(style)) {
6840 "\"%s\": bad value \"%s\" for gameloss_style.",
6841 filename, sval);
6842 ok = FALSE;
6843 break;
6844 } else {
6845 game.info.gameloss_style |= style;
6846 }
6847 }
6848 free(slist);
6849 }
6850
6851 if (ok) {
6857 "civstyle.happy_cost");
6863 "civstyle.food_cost");
6865 = secfile_lookup_bool_default(file, TRUE, "civstyle.civil_war_enabled");
6866
6869 "civstyle.civil_war_bonus_celebrating");
6870
6873 "civstyle.civil_war_bonus_unhappy");
6874
6880 "civstyle.base_bribe_cost");
6886 "civstyle.ransom_gold");
6889 "civstyle.pillage_select");
6890
6893 "civstyle.tech_steal_allow_holes");
6896 "civstyle.tech_trade_allow_holes");
6899 "civstyle.tech_trade_loss_allow_holes");
6902 "civstyle.tech_parasite_allow_holes");
6905 "civstyle.tech_loss_allow_holes");
6906
6912 "civstyle.upgrade_veteran_loss");
6918 "civstyle.autoupgrade_veteran_loss");
6919
6925 "research.base_tech_cost");
6926
6927 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
6928 /* base_tech_cost used to be used for this too. */
6934 "research.min_tech_cost");
6935 } else {
6941 "research.min_tech_cost");
6942 }
6943
6945 "civstyle.granary_food_ini");
6947
6950 "Too many granary_food_ini entries (%d, max %d)",
6952 ok = FALSE;
6953 } else if (game.info.granary_num_inis == 0) {
6954 log_error("No values for granary_food_ini. Using default "
6955 "value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
6958 } else {
6959 int gi;
6960
6961 /* check for <= 0 entries */
6962 for (gi = 0; gi < game.info.granary_num_inis; gi++) {
6963 if (food_ini[gi] <= 0) {
6964 if (gi == 0) {
6966 } else {
6967 food_ini[gi] = food_ini[gi - 1];
6968 }
6969 log_error("Bad value for granary_food_ini[%i]. Using %i.",
6970 gi, food_ini[gi]);
6971 }
6973 }
6974 }
6975 free(food_ini);
6976 }
6977
6978 if (ok) {
6984 "civstyle.granary_food_inc");
6985
6992 "civstyle.min_city_center_%s",
6995 }
6996
6997 if (ok) {
6998 const char *tus_text;
6999
7005 "civstyle.init_vis_radius_sq");
7006
7012 "civstyle.init_city_radius_sq");
7013
7015 "civstyle.gold_upkeep_style");
7020 "Unknown gold upkeep style \"%s\"",
7021 tus_text);
7022 ok = FALSE;
7023 }
7024
7026 = secfile_lookup_bool_default(file, FALSE, "civstyle.homeless_gold_upkeep");
7027
7031 "Cannot have homeless_gold_upkeep while gold_upkeep_style \"City\".");
7032 ok = FALSE;
7033 }
7034
7036 "civstyle.output_granularity");
7037
7039 = secfile_lookup_bool_default(file, FALSE, "civstyle.airlift_from_always_enabled");
7040
7042 = secfile_lookup_bool_default(file, TRUE, "civstyle.airlift_to_always_enabled");
7043
7044 /* section: wonder_visibility */
7045 if (ok) {
7046 const char *text;
7047
7048 text = secfile_lookup_str_default(file,
7050 "wonder_visibility.small_wonders");
7051
7056 "Unknown wonder visibility type \"%s\"",
7057 text);
7058 ok = FALSE;
7059 }
7060 }
7061
7062 /* section: illness */
7065 "illness.illness_on");
7071 "illness.illness_base_factor");
7077 "illness.illness_min_size");
7083 "illness.illness_trade_infection");
7089 "illness.illness_pollution_factor");
7090
7091 /* section: incite_cost */
7097 "incite_cost.base_incite_cost");
7103 "incite_cost.improvement_factor");
7109 "incite_cost.unit_factor");
7115 "incite_cost.total_factor");
7116 }
7117
7118 if (ok) {
7119 const char *tus_text;
7120
7121 /* section: combat_rules */
7124 "combat_rules.tired_attack");
7125
7128 "combat_rules.only_killing_makes_veteran");
7129
7132 "combat_rules.only_real_fight_makes_veteran");
7133
7136 "combat_rules.combat_odds_scaled_veterancy");
7137
7140 "combat_rules.damage_reduces_bombard_rate");
7141
7144 "combat_rules.low_firepower_badwallattacker");
7147 "combat_rules.low_firepower_pearl_harbour");
7150 "combat_rules.low_firepower_combat_bonus");
7153 "combat_rules.low_firepower_nonnat_bombard");
7154
7159 "combat_rules.nuke_pop_loss_pct");
7160
7165 "combat_rules.nuke_defender_survival_chance_pct");
7166
7167 /* section: borders */
7173 "borders.radius_sq_city");
7179 "borders.size_effect");
7180
7186 "borders.radius_sq_city_permanent");
7187
7188 /* section: research */
7190 "research.tech_cost_style");
7195 "Unknown tech cost style \"%s\"",
7196 tus_text);
7197 ok = FALSE;
7198 }
7199
7201 "research.tech_leakage");
7206 "Unknown tech leakage \"%s\"",
7207 tus_text);
7208 ok = FALSE;
7209 }
7212 log_error("Only tech_leakage \"%s\" supported with "
7213 "tech_cost_style \"%s\". ",
7216 log_error("Switching to tech_leakage \"%s\".",
7219 }
7225 "research.base_tech_cost");
7226
7228 "research.tech_upkeep_style");
7229
7231
7234 "Unknown tech upkeep style \"%s\"",
7235 tus_text);
7236 ok = FALSE;
7237 }
7238 }
7239
7240 if (ok) {
7246 "research.tech_upkeep_divider");
7247
7248 sval = secfile_lookup_str_default(file, NULL, "research.free_tech_method");
7249 if (sval == NULL) {
7251 "No free_tech_method given");
7252 ok = FALSE;
7253 } else {
7257 "Bad value %s for free_tech_method.", sval);
7258 ok = FALSE;
7259 }
7260 }
7261 }
7262
7263 if (ok) {
7264 int cf;
7265
7266 /* section: culture */
7269 "culture.victory_min_points");
7272 "culture.victory_lead_pct");
7275 "culture.migration_pml");
7278 "culture.history_interest_pml");
7279
7280 /* section: calendar */
7283 "calendar.skip_year_0");
7286 "calendar.start_year");
7288 = secfile_lookup_int_default(file, 0, "calendar.fragments");
7289
7292 "Too many calendar fragments. Max is %d",
7294 ok = FALSE;
7296 }
7300 "calendar.positive_label"));
7304 "calendar.negative_label"));
7305
7306 for (cf = 0; cf < game.calendar.calendar_fragments; cf++) {
7307 const char *fname;
7308
7309 fname = secfile_lookup_str_default(file, NULL, "calendar.fragment_name%d", cf);
7310 if (fname != NULL) {
7313 }
7314 }
7315 }
7316
7317 if (ok) {
7318 /* section playercolors */
7319 struct rgbcolor *prgbcolor = NULL;
7320 bool color_read = TRUE;
7321
7322 /* Check if the player list is defined and empty. */
7323 if (playercolor_count() != 0) {
7324 ok = FALSE;
7325 } else {
7326 i = 0;
7327
7328 while (color_read) {
7329 prgbcolor = NULL;
7330
7331 color_read = rgbcolor_load(file, &prgbcolor, "playercolors.colorlist%d", i);
7332 if (color_read) {
7334 }
7335
7336 i++;
7337 }
7338
7339 if (playercolor_count() == 0) {
7340 ruleset_error(NULL, LOG_ERROR, "No player colors defined!");
7341 ok = FALSE;
7342 }
7343
7344 if (ok) {
7346 if (!rgbcolor_load(file, &game.plr_bg_color, "playercolors.background")) {
7348 "No background player color defined! (%s)",
7349 secfile_error());
7350 ok = FALSE;
7351 }
7352 }
7353 }
7354 }
7355
7356 if (ok) {
7357 /* section: teams */
7358 svec = secfile_lookup_str_vec(file, &teams, "teams.names");
7359 if (team_slot_count() < teams) {
7361 }
7363 for (i = 0; i < teams; i++) {
7365 }
7366 free(svec);
7367
7369 nval = (NULL != sec ? section_list_size(sec) : 0);
7370 if (nval > MAX_DISASTER_TYPES) {
7371 int num = nval; /* No "size_t" to printf */
7372
7374 "\"%s\": Too many disaster types (%d, max %d)",
7375 filename, num, MAX_DISASTER_TYPES);
7377 ok = FALSE;
7378 } else {
7380 }
7381 }
7382
7383 if (ok) {
7385 int id = disaster_index(pdis);
7386 int j;
7387 size_t eff_count;
7388 struct requirement_vector *reqs;
7389 const char *sec_name = section_name(section_list_get(sec, id));
7390
7391 if (!ruleset_load_names(&pdis->name, NULL, file, sec_name)) {
7393 "\"%s\": Cannot load disaster names",
7394 filename);
7395 ok = FALSE;
7396 break;
7397 }
7398
7400 if (reqs == NULL) {
7401 ok = FALSE;
7402 break;
7403 }
7405
7407 "%s.frequency", sec_name);
7408
7409 svec = secfile_lookup_str_vec(file, &eff_count, "%s.effects", sec_name);
7410
7411 BV_CLR_ALL(pdis->effects);
7412 for (j = 0; j < eff_count; j++) {
7413 const char *dsval = svec[j];
7415
7417
7420 "\"%s\" disaster \"%s\": unknown effect \"%s\".",
7421 filename, disaster_rule_name(pdis), dsval);
7422 ok = FALSE;
7423 break;
7424 } else {
7425 BV_SET(pdis->effects, effect);
7426 }
7427 }
7428
7429 free(svec);
7430
7431 if (!ok) {
7432 break;
7433 }
7436 }
7437
7438 if (ok) {
7440
7442 int id = achievement_index(pach);
7443 const char *sec_name = section_name(section_list_get(sec, id));
7444 const char *typename;
7445 const char *msg;
7446
7447 typename = secfile_lookup_str_default(file, NULL, "%s.type", sec_name);
7448
7449 pach->type = achievement_type_by_name(typename, fc_strcasecmp);
7450 if (!achievement_type_is_valid(pach->type)) {
7452 "Achievement has unknown type \"%s\".",
7453 typename != NULL ? typename : "(NULL)");
7454 ok = FALSE;
7455 }
7456
7457 if (ok) {
7459 "%s.unique", sec_name);
7460
7462 "%s.value", sec_name);
7463 pach->culture = secfile_lookup_int_default(file, 0,
7464 "%s.culture", sec_name);
7465
7466 msg = secfile_lookup_str_default(file, NULL, "%s.first_msg", sec_name);
7467 if (msg == NULL) {
7469 "Achievement %s has no first msg!", sec_name);
7470 ok = FALSE;
7471 } else {
7472 pach->first_msg = fc_strdup(msg);
7473 }
7474 }
7475
7476 if (ok) {
7477 msg = secfile_lookup_str_default(file, NULL, "%s.cons_msg", sec_name);
7478 if (msg == NULL) {
7479 if (!pach->unique) {
7481 "Achievement %s has no msg for consecutive gainers!",
7482 sec_name);
7483 ok = FALSE;
7484 }
7485 } else {
7486 pach->cons_msg = fc_strdup(msg);
7487 }
7488 }
7489
7490 if (!ok) {
7491 break;
7492 }
7495 }
7496
7497 if (ok) {
7498 for (i = 0; (name = secfile_lookup_str_default(file, NULL,
7499 "trade.settings%d.type",
7500 i)); i++) {
7502
7503 if (type == TRT_LAST) {
7505 "\"%s\" unknown trade route type \"%s\".",
7506 filename, name);
7507 ok = FALSE;
7508 } else {
7510 const char *cancelling;
7511 const char *bonus;
7512
7513 set->trade_pct = secfile_lookup_int_default(file, 100,
7514 "trade.settings%d.pct", i);
7515 cancelling = secfile_lookup_str_default(file, "Active",
7516 "trade.settings%d.cancelling", i);
7518 if (set->cancelling == TRI_LAST) {
7520 "\"%s\" unknown trade route cancelling type \"%s\".",
7521 filename, cancelling);
7522 ok = FALSE;
7523 }
7524
7525 bonus = secfile_lookup_str_default(file, "None", "trade.settings%d.bonus", i);
7526
7528
7531 "\"%s\" unknown trade route bonus type \"%s\".",
7532 filename, bonus);
7533 ok = FALSE;
7534 }
7535 }
7536 }
7537 }
7538
7539 if (ok) {
7540 const char *str;
7541 bool reveal_default = FALSE;
7542
7544 = secfile_lookup_int_default(file, 0, "trade.min_trade_route_val");
7545
7546 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
7547 /* Old hardcoded behavior was to reveal the trade partner. */
7549 }
7550
7553 "trade.reveal_trade_partner");
7554
7557 "trade.goods_selection");
7558
7560
7563 "\"%s\" goods selection method \"%s\" unknown.",
7564 filename, str);
7565 ok = FALSE;
7566 }
7567 }
7568
7569 if (ok) {
7571
7573 int id = goods_index(pgood);
7574 const char *sec_name = section_name(section_list_get(sec, id));
7575 struct requirement_vector *reqs;
7576 const char **slist;
7577 int j;
7578
7580 if (reqs == NULL) {
7581 ok = FALSE;
7582 break;
7583 }
7585
7586 pgood->from_pct = secfile_lookup_int_default(file, 100,
7587 "%s.from_pct", sec_name);
7588 pgood->to_pct = secfile_lookup_int_default(file, 100,
7589 "%s.to_pct", sec_name);
7590 pgood->onetime_pct = secfile_lookup_int_default(file, 100,
7591 "%s.onetime_pct", sec_name);
7592
7593 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
7594 BV_CLR_ALL(pgood->flags);
7595 for (j = 0; j < nval; j++) {
7596 enum goods_flag_id flag;
7597
7598 sval = slist[j];
7600 if (!goods_flag_id_is_valid(flag)) {
7601 ruleset_error(NULL, LOG_ERROR, "\"%s\" good \"%s\": unknown flag \"%s\".",
7602 filename, goods_rule_name(pgood), sval);
7603 ok = FALSE;
7604 break;
7605 } else {
7606 BV_SET(pgood->flags, flag);
7607 }
7608 }
7609 free(slist);
7610
7611 pgood->helptext = lookup_strvec(file, sec_name, "helptext");
7614 }
7615
7616 if (ok) {
7618
7619 if (sec != NULL) {
7620 int num = section_list_size(sec);
7621
7622 for (i = 0; i < num; i++) {
7623 const char *sec_name = section_name(section_list_get(sec, i));
7624 const char *clause_name = secfile_lookup_str_default(file, NULL,
7625 "%s.type", sec_name);
7627 struct clause_info *info;
7628 struct requirement_vector *reqs;
7629
7630 if (!clause_type_is_valid(type)) {
7632 "\"%s\" unknown clause type \"%s\".",
7633 filename, clause_name);
7634 ok = FALSE;
7635 break;
7636 }
7637
7638 info = clause_info_get(type);
7639
7640 if (info->enabled) {
7642 "\"%s\" duplicate clause type \"%s\" definition.",
7643 filename, clause_name);
7644 ok = FALSE;
7645 break;
7646 }
7647
7648 reqs = lookup_req_list(file, compat, sec_name, "giver_reqs", clause_name);
7649 if (reqs == NULL) {
7650 ok = FALSE;
7651 break;
7652 }
7654
7655 reqs = lookup_req_list(file, compat, sec_name, "receiver_reqs", clause_name);
7656 if (reqs == NULL) {
7657 ok = FALSE;
7658 break;
7659 }
7661
7662 info->enabled = TRUE;
7663 }
7664 }
7666 }
7667
7668 if (ok) {
7670
7671 if (sec != NULL) {
7672 int num = section_list_size(sec);
7673 int curr;
7674
7675 for (curr = 0; curr < num; curr++) {
7676
7677 struct counter *pcount = counter_by_id(curr);
7678 const char *sec_name = section_name(section_list_get(sec, curr));
7679 const char *counter_type = secfile_lookup_str_default(file, NULL,
7680 "%s.type",
7681 sec_name);
7682
7685 if (!counter_behaviour_is_valid(cb)) {
7687 "\"%s\" unknown counter type \"%s\".",
7688 filename, counter_type);
7689 ok = FALSE;
7690 break;
7691 }
7692
7693 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
7695 "\"%s\": Cannot load counter names",
7696 filename);
7697 ok = FALSE;
7698 break;
7699 }
7700
7701 pcount->helptext = lookup_strvec(file, sec_name, "helptext");
7702 pcount->type = cb;
7703 if (!secfile_lookup_int(file, &pcount->checkpoint,
7704 "%s.checkpoint", sec_name)) {
7705
7707 "\"%s\": No checkpoint value",
7708 filename);
7709 ok = FALSE;
7710 break;
7711 }
7712
7713 pcount->target = CTGT_CITY;
7714 pcount->index = curr;
7715 pcount->def = secfile_lookup_int_default(file, 0,
7716 "%s.def",
7717 sec_name);
7719 }
7720 }
7721 }
7722
7723 /* secfile_check_unused() is not here, but only after also settings section
7724 * has been loaded. */
7725
7726 return ok;
7727}
7728
7729/**********************************************************************/
7732static bool load_ruleset_actions(struct section_file *file,
7733 struct section_file *gamefile,
7734 struct rscompat_info *compat)
7735{
7736 bool ok = TRUE;
7737 const char *filename = secfile_name(file);
7738 struct section_list *sec;
7740 struct requirement_vector *reqs;
7741
7742 /* Auto attack. */
7743
7744 /* Action auto performers aren't ready to be exposed in the ruleset
7745 * yet. The behavior when two action auto performers for the same
7746 * cause can fire isn't set in stone yet. How is one of them chosen?
7747 * What if all the actions of the chosen action auto performer turned
7748 * out to be illegal but one of the other action auto performers that
7749 * fired has legal actions? These issues can decide what other action
7750 * rules action auto performers can represent in the future. Deciding
7751 * should therefore wait until a rule needs action auto performers to
7752 * work a certain way. */
7753 /* Only one action auto performer, ACTION_AUTO_MOVED_ADJ, is caused
7754 * by AAPC_UNIT_MOVED_ADJ. It is therefore safe to expose the full
7755 * requirement vector to the ruleset. */
7756
7757 /* A unit moved next to this unit and the autoattack server setting
7758 * is enabled. */
7761
7762 reqs = lookup_req_list(file, compat,
7763 "auto_attack", "if_attacker",
7764 "auto_attack");
7765 if (reqs == NULL) {
7766 ok = FALSE;
7767 } else {
7769
7771 "auto_attack.attack_actions",
7772 filename)) {
7773 /* Failed to load auto attack actions */
7775 "\"%s\": %s: failed load %s.",
7776 filename, "auto_attack", "attack_actions");
7777 ok = FALSE;
7778 }
7779 }
7780
7781 /* Section: actions */
7782 if (ok) {
7783 action_iterate(act_id) {
7784 struct action *paction = action_by_number(act_id);
7785
7786 if (!load_action_blocked_by_list(file, filename, paction)) {
7787 ok = FALSE;
7788 break;
7789 }
7791
7792 if (ok) {
7793 if (!lookup_bv_actions(file, filename,
7795 "actions.diplchance_initial_odds")) {
7796 ok = FALSE;
7797 }
7798 }
7799
7800 if (ok) {
7801 /* If the "Poison City" action or the "Poison City Escape" action
7802 * should empty the granary. */
7803 /* TODO: empty granary and reduce population should become separate
7804 * action effect flags when actions are generalized. */
7808 "actions.poison_empties_food_stock");
7809
7810 /* If the "Steal Maps" action or the "Steal Maps Escape" action always
7811 * will reveal all cities when successful. */
7815 "actions.steal_maps_reveals_all_cities");
7816
7817 /* Allow setting certain properties for some actions before
7818 * generalized actions. */
7819 action_iterate(act_id) {
7820 if (!load_action_range(file, act_id)) {
7821 ok = FALSE;
7822 } else if (!load_action_kind(file, act_id)) {
7823 ok = FALSE;
7824 } else if (!load_action_actor_consuming_always(file, act_id)) {
7825 ok = FALSE;
7826 } else {
7827 load_action_ui_name(file, act_id,
7830 }
7831
7832 if (!ok) {
7833 break;
7834 }
7836
7837 if (ok && compat->compat_mode && compat->version < RSFORMAT_3_2) {
7838 secfile_entry_ignore_by_path(file, "actions.ui_name_clean_pollution");
7839 secfile_entry_ignore_by_path(file, "actions.ui_name_clean_fallout");
7840 }
7841 }
7842
7843 if (ok) {
7844 /* The quiet (don't auto generate help for) property of all actions
7845 * live in a single enum vector. This avoids generic action
7846 * expectations. */
7847 if (secfile_entry_by_path(file, "actions.quiet_actions")) {
7849 size_t asize;
7850 int j;
7851
7854 "actions.quiet_actions");
7855
7856 if (!quiet_actions) {
7857 /* Entity exists but couldn't read it. */
7859 "\"%s\": actions.quiet_actions: bad action list",
7860 filename);
7861
7862 ok = FALSE;
7863 } else {
7864 for (j = 0; j < asize; j++) {
7865 /* Don't auto generate help text for this action. */
7867 }
7868
7870 }
7871 }
7872 }
7873
7874 if (ok) {
7875 /* Hard code action sub results for now. */
7876
7877 /* Unit Enter Hut */
7879 BV_SET(paction->sub_results, ACT_SUB_RES_HUT_ENTER);
7889
7890 /* Unit Frighten Hut */
7902
7903 /* Unit May Embark */
7904 action_iterate(act_id) {
7905 struct action *paction = action_by_number(act_id);
7906
7908 "civstyle.paradrop_to_transport")
7911 BV_SET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK);
7912 }
7913
7914 /* Embark actions will always embark, not maybe embark. */
7916
7917 /* Non Lethal bombard */
7924 }
7925 }
7926
7927 if (ok) {
7928 /* Forced actions after another action was successfully performed. */
7929
7930 if (!load_action_post_success_force(file, filename,
7934 ok = FALSE;
7935 } else if (!load_action_post_success_force(file, filename,
7938 ACTION_ATTACK))) {
7939 ok = FALSE;
7940 } else if (!load_action_post_success_force(file, filename,
7943 ACTION_ATTACK2))) {
7944 ok = FALSE;
7945 } else if (!load_action_post_success_force(file, filename,
7949 ok = FALSE;
7950 } else if (!load_action_post_success_force(file, filename,
7954 ok = FALSE;
7955 }
7956
7957 /* No "Suicide Attack". Can't act when dead. */
7958 }
7959
7960 if (ok) {
7961 /* The city that made the unit's current tile native is gone.
7962 * Evaluated against an adjacent tile. */
7964 auto_perf->cause = AAPC_CITY_GONE;
7965
7966 /* I have no objections to moving this out of game's actions to
7967 * cities.ruleset, units.ruleset or an other location in game.ruleset
7968 * you find more suitable. -- Sveinung */
7970 "actions.escape_city", filename)) {
7971 ok = FALSE;
7972 }
7973 }
7974
7975 if (ok) {
7976 /* The unit's stack has been defeated and is scheduled for execution
7977 * but the unit has the CanEscape unit type flag.
7978 * Evaluated against an adjacent tile. */
7981
7982 /* I have no objections to moving this out of game's actions to
7983 * cities.ruleset, units.ruleset or an other location in game.ruleset
7984 * you find more suitable. -- Sveinung */
7986 "actions.unit_stack_death", filename)) {
7987 ok = FALSE;
7988 }
7989 }
7990
7991 if (ok) {
7994
7995 if (sec) {
7996 section_list_iterate(sec, psection) {
7997 struct action_enabler *enabler;
7998 const char *sec_name = section_name(psection);
7999 struct action *paction;
8000 struct requirement_vector *actor_reqs;
8001 struct requirement_vector *target_reqs;
8002 const char *action_text;
8003 const char *orig_name;
8004
8006
8007 orig_name = secfile_lookup_str(file, "%s.action", sec_name);
8008
8010
8011 if (action_text == NULL) {
8013 "\"%s\" [%s] missing action to enable.",
8014 filename, sec_name);
8015 ok = FALSE;
8016 break;
8017 }
8018
8020 if (!paction) {
8022 "\"%s\" [%s] lists unknown action type \"%s\".",
8023 filename, sec_name, action_text);
8024 ok = FALSE;
8025 break;
8026 }
8027
8028 enabler->action = action_id(paction);
8029
8030 actor_reqs = lookup_req_list(file, compat, sec_name, "actor_reqs", action_text);
8031 if (actor_reqs == NULL) {
8032 ok = FALSE;
8033 break;
8034 }
8035
8036 requirement_vector_copy(&enabler->actor_reqs, actor_reqs);
8037
8038 target_reqs = lookup_req_list(file, compat, sec_name, "target_reqs", action_text);
8039 if (target_reqs == NULL) {
8040 ok = FALSE;
8041 break;
8042 }
8043
8044 requirement_vector_copy(&enabler->target_reqs, target_reqs);
8045
8047
8050
8052 }
8053 }
8054
8055 return ok;
8056}
8057
8058/**********************************************************************/
8062static void send_ruleset_unit_classes(struct conn_list *dest)
8063{
8064 struct packet_ruleset_unit_class packet;
8066 int i;
8067
8068 for (i = 0; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
8069 const char *flagname;
8070 const char *helptxt;
8071
8073
8075 if (flagname == NULL) {
8076 fpacket.name[0] = '\0';
8077 } else {
8079 }
8080
8082 if (helptxt == NULL) {
8083 fpacket.helptxt[0] = '\0';
8084 } else {
8085 sz_strlcpy(fpacket.helptxt, helptxt);
8086 }
8087
8089 }
8090
8092 packet.id = uclass_number(c);
8093 sz_strlcpy(packet.name, untranslated_name(&c->name));
8094 sz_strlcpy(packet.rule_name, rule_name_get(&c->name));
8095 packet.min_speed = c->min_speed;
8096 packet.hp_loss_pct = c->hp_loss_pct;
8097 packet.non_native_def_pct = c->non_native_def_pct;
8098 packet.flags = c->flags;
8099
8100 PACKET_STRVEC_COMPUTE(packet.helptext, c->helptext);
8101
8102 lsend_packet_ruleset_unit_class(dest, &packet);
8104}
8105
8106/**********************************************************************/
8110static void send_ruleset_units(struct conn_list *dest)
8111{
8112 struct packet_ruleset_unit packet;
8113#ifdef FREECIV_WEB
8115#endif /* FREECIV_WEB */
8117 int i;
8118
8119 for (i = 0; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
8120 const char *flagname;
8121 const char *helptxt;
8122
8124
8126 if (flagname == NULL) {
8127 fpacket.name[0] = '\0';
8128 } else {
8130 }
8131
8133 if (helptxt == NULL) {
8134 fpacket.helptxt[0] = '\0';
8135 } else {
8136 sz_strlcpy(fpacket.helptxt, helptxt);
8137 }
8138
8140 }
8141
8143 packet.id = utype_number(u);
8144 sz_strlcpy(packet.name, untranslated_name(&u->name));
8145 sz_strlcpy(packet.rule_name, rule_name_get(&u->name));
8146 sz_strlcpy(packet.sound_move, u->sound_move);
8147 sz_strlcpy(packet.sound_move_alt, u->sound_move_alt);
8148 sz_strlcpy(packet.sound_fight, u->sound_fight);
8149 sz_strlcpy(packet.sound_fight_alt, u->sound_fight_alt);
8150 sz_strlcpy(packet.graphic_str, u->graphic_str);
8151 sz_strlcpy(packet.graphic_alt, u->graphic_alt);
8152 sz_strlcpy(packet.graphic_alt2, u->graphic_alt2);
8154 packet.build_cost = u->build_cost;
8155 packet.pop_cost = u->pop_cost;
8156 packet.attack_strength = u->attack_strength;
8157 packet.defense_strength = u->defense_strength;
8158 packet.move_rate = u->move_rate;
8159
8160 i = 0;
8161 requirement_vector_iterate(&u->build_reqs, req) {
8162 packet.build_reqs[i++] = *req;
8164 packet.build_reqs_count = i;
8165
8166 packet.vision_radius_sq = u->vision_radius_sq;
8167 packet.transport_capacity = u->transport_capacity;
8168 packet.hp = u->hp;
8169 packet.firepower = u->firepower;
8170 packet.obsoleted_by = u->obsoleted_by
8171 ? utype_number(u->obsoleted_by)
8172 : utype_count();
8173 packet.converted_to = u->converted_to
8174 ? utype_number(u->converted_to)
8175 : utype_count();
8176 packet.convert_time = u->convert_time;
8177 packet.fuel = u->fuel;
8178 packet.flags = u->flags;
8179 packet.roles = u->roles;
8180 packet.happy_cost = u->happy_cost;
8182 packet.upkeep[o] = u->upkeep[o];
8184 packet.paratroopers_range = u->paratroopers_range;
8185 packet.bombard_rate = u->bombard_rate;
8186 packet.city_size = u->city_size;
8187 packet.city_slots = u->city_slots;
8188 packet.tp_defense = u->tp_defense;
8189 packet.cargo = u->cargo;
8190 packet.targets = u->targets;
8191 packet.embarks = u->embarks;
8192 packet.disembarks = u->disembarks;
8193 packet.vlayer = u->vlayer;
8194
8195 if (u->veteran == NULL) {
8196 /* Use the default veteran system. */
8197 packet.veteran_levels = 0;
8198 } else {
8199 /* Per unit veteran system definition. */
8201
8202 for (i = 0; i < packet.veteran_levels; i++) {
8203 const struct veteran_level *vlevel = utype_veteran_level(u, i);
8204
8206 packet.power_fact[i] = vlevel->power_fact;
8207 packet.move_bonus[i] = vlevel->move_bonus;
8208 packet.base_raise_chance[i] = vlevel->base_raise_chance;
8209 packet.work_raise_chance[i] = vlevel->work_raise_chance;
8210 }
8211 }
8212 PACKET_STRVEC_COMPUTE(packet.helptext, u->helptext);
8213
8214 packet.worker = u->adv.worker;
8215
8216#ifdef FREECIV_WEB
8217 web_packet.id = utype_number(u);
8218
8219 BV_CLR_ALL(web_packet.utype_actions);
8220
8221 action_iterate(act) {
8222 if (utype_can_do_action(u, act)) {
8223 BV_SET(web_packet.utype_actions, act);
8224 }
8226#endif /* FREECIV_WEB */
8227
8228 lsend_packet_ruleset_unit(dest, &packet);
8230
8231 combat_bonus_list_iterate(u->bonuses, pbonus) {
8233
8234 bonuspacket.unit = packet.id;
8235 bonuspacket.flag = pbonus->flag;
8236 bonuspacket.type = pbonus->type;
8237 bonuspacket.value = pbonus->value;
8238 bonuspacket.quiet = pbonus->quiet;
8239
8243}
8244
8245/**********************************************************************/
8249static void send_ruleset_specialists(struct conn_list *dest)
8250{
8251 struct packet_ruleset_specialist packet;
8252
8255 int j;
8256
8257 packet.id = spec_id;
8259 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
8263 j = 0;
8265 packet.reqs[j++] = *preq;
8267 packet.reqs_count = j;
8268
8270
8271 lsend_packet_ruleset_specialist(dest, &packet);
8273}
8274/**********************************************************************/
8277static void send_ruleset_tech_classes(struct conn_list *dest)
8278{
8279 struct packet_ruleset_tech_class packet;
8280
8282 packet.id = ptclass->idx;
8283 sz_strlcpy(packet.name, untranslated_name(&ptclass->name));
8284 sz_strlcpy(packet.rule_name, rule_name_get(&ptclass->name));
8285 packet.cost_pct = ptclass->cost_pct;
8286
8287 lsend_packet_ruleset_tech_class(dest, &packet);
8289}
8290
8291/**********************************************************************/
8295static void send_ruleset_techs(struct conn_list *dest)
8296{
8297 struct packet_ruleset_tech packet;
8299 int i;
8300
8301 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
8302 const char *flagname;
8303 const char *helptxt;
8304
8305 fpacket.id = i + TECH_USER_1;
8306
8308 if (flagname == NULL) {
8309 fpacket.name[0] = '\0';
8310 } else {
8312 }
8313
8315 if (helptxt == NULL) {
8316 fpacket.helptxt[0] = '\0';
8317 } else {
8318 sz_strlcpy(fpacket.helptxt, helptxt);
8319 }
8320
8322 }
8323
8324 advance_iterate(a) {
8325 packet.id = advance_number(a);
8326 packet.removed = !valid_advance(a);
8327 if (a->tclass == NULL) {
8328 packet.tclass = 0;
8329 } else {
8330 packet.tclass = a->tclass->idx;
8331 }
8332 sz_strlcpy(packet.name, untranslated_name(&a->name));
8333 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8334 sz_strlcpy(packet.graphic_str, a->graphic_str);
8335 sz_strlcpy(packet.graphic_alt, a->graphic_alt);
8336
8337 /* Current size of the packet's research_reqs requirement vector. */
8338 i = 0;
8339
8340 /* The requirements req1 and req2 are needed to research a tech. Send
8341 * them in the research_reqs requirement vector. Range is set to player
8342 * since pooled research is configurable. */
8343
8344 if ((a->require[AR_ONE] != A_NEVER)
8345 && advance_number(a->require[AR_ONE]) > A_NONE) {
8346 packet.research_reqs[i++]
8348 FALSE, TRUE, FALSE,
8349 advance_number(a->require[AR_ONE]));
8350 }
8351
8352 if ((a->require[AR_TWO] != A_NEVER)
8353 && advance_number(a->require[AR_TWO]) > A_NONE) {
8354 packet.research_reqs[i++]
8356 FALSE, TRUE, FALSE,
8357 advance_number(a->require[AR_TWO]));;
8358 }
8359
8360 /* The requirements of the tech's research_reqs also goes in the
8361 * packet's research_reqs requirement vector. */
8362 requirement_vector_iterate(&a->research_reqs, req) {
8363 packet.research_reqs[i++] = *req;
8365
8366 /* The packet's research_reqs should contain req1, req2 and the
8367 * requirements of the tech's research_reqs. */
8368 packet.research_reqs_count = i;
8369
8370 packet.root_req = a->require[AR_ROOT]
8371 ? advance_number(a->require[AR_ROOT])
8372 : advance_count();
8373
8374 packet.flags = a->flags;
8375 packet.cost = a->cost;
8376 packet.num_reqs = a->num_reqs;
8377 PACKET_STRVEC_COMPUTE(packet.helptext, a->helptext);
8378
8379 lsend_packet_ruleset_tech(dest, &packet);
8381}
8382
8383/**********************************************************************/
8386static void send_ruleset_counters(struct conn_list *dest)
8387{
8389 struct packet_ruleset_counter packet;
8390
8391 sz_strlcpy(packet.name, untranslated_name(&pcount->name));
8392 sz_strlcpy(packet.rule_name, rule_name_get(&pcount->name));
8393 packet.checkpoint = pcount->checkpoint;
8394 packet.behaviour = pcount->type;
8395 packet.type = pcount->target;
8396 packet.def = pcount->def;
8397
8398 PACKET_STRVEC_COMPUTE(packet.helptext, pcount->helptext);
8399 lsend_packet_ruleset_counter(dest, &packet);
8401}
8402
8403/**********************************************************************/
8407static void send_ruleset_buildings(struct conn_list *dest)
8408{
8409 int i;
8410
8411 for (i = 0; i < MAX_NUM_USER_BUILDING_FLAGS; i++) {
8413 const char *flagname;
8414 const char *helptxt;
8415
8417
8419 if (flagname == NULL) {
8420 fpacket.name[0] = '\0';
8421 } else {
8423 }
8424
8426 if (helptxt == NULL) {
8427 fpacket.helptxt[0] = '\0';
8428 } else {
8429 sz_strlcpy(fpacket.helptxt, helptxt);
8430 }
8431
8433 }
8434
8436 struct packet_ruleset_building packet;
8437 int j;
8438
8439 packet.id = improvement_number(b);
8440 packet.genus = b->genus;
8441 sz_strlcpy(packet.name, untranslated_name(&b->name));
8442 sz_strlcpy(packet.rule_name, rule_name_get(&b->name));
8443 sz_strlcpy(packet.graphic_str, b->graphic_str);
8444 sz_strlcpy(packet.graphic_alt, b->graphic_alt);
8445 sz_strlcpy(packet.graphic_alt2, b->graphic_alt2);
8446 j = 0;
8447 requirement_vector_iterate(&b->reqs, preq) {
8448 packet.reqs[j++] = *preq;
8450 packet.reqs_count = j;
8451 j = 0;
8452 requirement_vector_iterate(&b->obsolete_by, pobs) {
8453 packet.obs_reqs[j++] = *pobs;
8455 packet.obs_count = j;
8456 packet.build_cost = b->build_cost;
8457 packet.upkeep = b->upkeep;
8458 packet.sabotage = b->sabotage;
8459 packet.flags = b->flags;
8460 sz_strlcpy(packet.soundtag, b->soundtag);
8461 sz_strlcpy(packet.soundtag_alt, b->soundtag_alt);
8462 sz_strlcpy(packet.soundtag_alt2, b->soundtag_alt2);
8463 PACKET_STRVEC_COMPUTE(packet.helptext, b->helptext);
8464
8465 lsend_packet_ruleset_building(dest, &packet);
8467}
8468
8469/**********************************************************************/
8473static void send_ruleset_terrain(struct conn_list *dest)
8474{
8475 struct packet_ruleset_terrain packet;
8477 int i;
8478
8480
8481 for (i = 0; i < MAX_NUM_USER_TER_FLAGS; i++) {
8482 const char *flagname;
8483 const char *helptxt;
8484
8485 fpacket.id = i + TER_USER_1;
8486
8488 if (flagname == NULL) {
8489 fpacket.name[0] = '\0';
8490 } else {
8492 }
8493
8495 if (helptxt == NULL) {
8496 fpacket.helptxt[0] = '\0';
8497 } else {
8498 sz_strlcpy(fpacket.helptxt, helptxt);
8499 }
8500
8502 }
8503
8504 terrain_type_iterate(pterrain) {
8505 packet.id = terrain_number(pterrain);
8506 packet.tclass = pterrain->tclass;
8507 packet.native_to = pterrain->native_to;
8508
8509 sz_strlcpy(packet.name, untranslated_name(&pterrain->name));
8510 sz_strlcpy(packet.rule_name, rule_name_get(&pterrain->name));
8511 sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
8512 sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
8513 sz_strlcpy(packet.graphic_alt2, pterrain->graphic_alt2);
8514
8515 packet.movement_cost = pterrain->movement_cost;
8516 packet.defense_bonus = pterrain->defense_bonus;
8517
8519 packet.output[o] = pterrain->output[o];
8521
8522 packet.num_resources = 0;
8523 terrain_resources_iterate(pterrain, res, freq) {
8524 packet.resources[packet.num_resources] = extra_number(res);
8525 packet.resource_freq[packet.num_resources] = freq;
8526 packet.num_resources++;
8528
8530 packet.road_output_incr_pct[o] = pterrain->road_output_incr_pct[o];
8532
8533 packet.base_time = pterrain->base_time;
8534 packet.road_time = pterrain->road_time;
8535
8536 packet.cultivate_result = (pterrain->cultivate_result
8537 ? terrain_number(pterrain->cultivate_result)
8538 : terrain_count());
8539 packet.cultivate_time = pterrain->cultivate_time;
8540
8541 packet.plant_result = (pterrain->plant_result
8542 ? terrain_number(pterrain->plant_result)
8543 : terrain_count());
8544 packet.plant_time = pterrain->plant_time;
8545
8546 packet.irrigation_food_incr = pterrain->irrigation_food_incr;
8547 packet.irrigation_time = pterrain->irrigation_time;
8548
8549 packet.mining_shield_incr = pterrain->mining_shield_incr;
8550 packet.mining_time = pterrain->mining_time;
8551
8552 packet.animal = (pterrain->animal == NULL ? -1 : utype_number(pterrain->animal));
8553 packet.transform_result = (pterrain->transform_result
8554 ? terrain_number(pterrain->transform_result)
8555 : terrain_count());
8556 packet.placing_time = pterrain->placing_time;
8557 packet.pillage_time = pterrain->pillage_time;
8558 packet.transform_time = pterrain->transform_time;
8559
8561 for (i = 0; i < game.control.num_extra_types; i++) {
8562 packet.extra_removal_times[i] = pterrain->extra_removal_times[i];
8563 }
8564
8565 packet.flags = pterrain->flags;
8566
8567 packet.color_red = pterrain->rgb->r;
8568 packet.color_green = pterrain->rgb->g;
8569 packet.color_blue = pterrain->rgb->b;
8570
8571 PACKET_STRVEC_COMPUTE(packet.helptext, pterrain->helptext);
8572
8573 lsend_packet_ruleset_terrain(dest, &packet);
8575}
8576
8577/**********************************************************************/
8580static void send_ruleset_resources(struct conn_list *dest)
8581{
8582 struct packet_ruleset_resource packet;
8583
8585 packet.id = extra_index(presource);
8586
8588 packet.output[o] = presource->data.resource->output[o];
8590
8591 lsend_packet_ruleset_resource(dest, &packet);
8593}
8594
8595/**********************************************************************/
8599static void send_ruleset_extras(struct conn_list *dest)
8600{
8601 int i;
8602
8603 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
8605 const char *flagname;
8606 const char *helptxt;
8607
8609
8611 if (flagname == NULL) {
8612 fpacket.name[0] = '\0';
8613 } else {
8615 }
8616
8618 if (helptxt == NULL) {
8619 fpacket.helptxt[0] = '\0';
8620 } else {
8621 sz_strlcpy(fpacket.helptxt, helptxt);
8622 }
8623
8625 }
8626
8628 struct packet_ruleset_extra packet;
8629 int j;
8630
8631 packet.id = extra_number(e);
8632 sz_strlcpy(packet.name, untranslated_name(&e->name));
8633 sz_strlcpy(packet.rule_name, rule_name_get(&e->name));
8634
8635 packet.category = e->category;
8636
8637 BV_CLR_ALL(packet.causes);
8638 for (j = 0; j < EC_COUNT; j++) {
8639 if (is_extra_caused_by(e, j)) {
8640 BV_SET(packet.causes, j);
8641 }
8642 }
8643
8644 BV_CLR_ALL(packet.rmcauses);
8645 for (j = 0; j < ERM_COUNT; j++) {
8646 if (is_extra_removed_by(e, j)) {
8647 BV_SET(packet.rmcauses, j);
8648 }
8649 }
8650
8651 sz_strlcpy(packet.activity_gfx, e->activity_gfx);
8652 sz_strlcpy(packet.act_gfx_alt, e->act_gfx_alt);
8653 sz_strlcpy(packet.act_gfx_alt2, e->act_gfx_alt2);
8654 sz_strlcpy(packet.rmact_gfx, e->rmact_gfx);
8655 sz_strlcpy(packet.rmact_gfx_alt, e->rmact_gfx_alt);
8656 sz_strlcpy(packet.rmact_gfx_alt2, e->rmact_gfx_alt2);
8657 sz_strlcpy(packet.graphic_str, e->graphic_str);
8658 sz_strlcpy(packet.graphic_alt, e->graphic_alt);
8659
8660 j = 0;
8661 requirement_vector_iterate(&e->reqs, preq) {
8662 packet.reqs[j++] = *preq;
8664 packet.reqs_count = j;
8665
8666 j = 0;
8667 requirement_vector_iterate(&e->rmreqs, preq) {
8668 packet.rmreqs[j++] = *preq;
8670 packet.rmreqs_count = j;
8671
8672 packet.appearance_chance = e->appearance_chance;
8673 j = 0;
8674 requirement_vector_iterate(&e->appearance_reqs, preq) {
8675 packet.appearance_reqs[j++] = *preq;
8677 packet.appearance_reqs_count = j;
8678
8679 packet.disappearance_chance = e->disappearance_chance;
8680 j = 0;
8681 requirement_vector_iterate(&e->disappearance_reqs, preq) {
8682 packet.disappearance_reqs[j++] = *preq;
8684 packet.disappearance_reqs_count = j;
8685
8686 packet.visibility_req = e->visibility_req;
8687 packet.buildable = e->buildable;
8688 packet.generated = e->generated;
8689 packet.build_time = e->build_time;
8690 packet.build_time_factor = e->build_time_factor;
8691 packet.removal_time = e->removal_time;
8692 packet.removal_time_factor = e->removal_time_factor;
8693 packet.infracost = e->infracost;
8694 packet.defense_bonus = e->defense_bonus;
8695 packet.eus = e->eus;
8696 packet.no_aggr_near_city = e->no_aggr_near_city;
8697
8698 packet.native_to = e->native_to;
8699
8700 packet.flags = e->flags;
8701 packet.hidden_by = e->hidden_by;
8702 packet.bridged_over = e->bridged_over;
8703 packet.conflicts = e->conflicts;
8704
8705 PACKET_STRVEC_COMPUTE(packet.helptext, e->helptext);
8706
8707 lsend_packet_ruleset_extra(dest, &packet);
8709}
8710
8711/**********************************************************************/
8715static void send_ruleset_bases(struct conn_list *dest)
8716{
8718 struct base_type *b = extra_base_get(pextra);
8719 struct packet_ruleset_base packet;
8720
8721 packet.id = base_number(b);
8722
8723 packet.gui_type = b->gui_type;
8724 packet.border_sq = b->border_sq;
8725 packet.vision_main_sq = b->vision_main_sq;
8726 packet.vision_invis_sq = b->vision_invis_sq;
8727 packet.vision_subs_sq = b->vision_subs_sq;
8728
8729 lsend_packet_ruleset_base(dest, &packet);
8731}
8732
8733/**********************************************************************/
8737static void send_ruleset_roads(struct conn_list *dest)
8738{
8739 struct packet_ruleset_road packet;
8740
8742 struct road_type *r = extra_road_get(pextra);
8743 int j;
8744
8745 packet.id = road_number(r);
8746
8747 packet.gui_type = r->gui_type;
8748
8749 j = 0;
8751 packet.first_reqs[j++] = *preq;
8753 packet.first_reqs_count = j;
8754
8755 packet.move_cost = r->move_cost;
8756 packet.move_mode = r->move_mode;
8757
8759 packet.tile_incr_const[o] = r->tile_incr_const[o];
8760 packet.tile_incr[o] = r->tile_incr[o];
8761 packet.tile_bonus[o] = r->tile_bonus[o];
8763
8764 packet.compat = r->compat;
8765
8766 packet.integrates = r->integrates;
8767 packet.flags = r->flags;
8768
8769 lsend_packet_ruleset_road(dest, &packet);
8771}
8772
8773/**********************************************************************/
8777static void send_ruleset_goods(struct conn_list *dest)
8778{
8779 struct packet_ruleset_goods packet;
8780
8782 int j;
8783
8784 packet.id = goods_number(g);
8785 sz_strlcpy(packet.name, untranslated_name(&g->name));
8786 sz_strlcpy(packet.rule_name, rule_name_get(&g->name));
8787
8788 j = 0;
8789 requirement_vector_iterate(&g->reqs, preq) {
8790 packet.reqs[j++] = *preq;
8792 packet.reqs_count = j;
8793
8794 packet.from_pct = g->from_pct;
8795 packet.to_pct = g->to_pct;
8796 packet.onetime_pct = g->onetime_pct;
8797 packet.flags = g->flags;
8798
8799 PACKET_STRVEC_COMPUTE(packet.helptext, g->helptext);
8800
8801 lsend_packet_ruleset_goods(dest, &packet);
8803}
8804
8805/**********************************************************************/
8809static void send_ruleset_disasters(struct conn_list *dest)
8810{
8811 struct packet_ruleset_disaster packet;
8812
8814 int j;
8815
8816 packet.id = disaster_number(d);
8817
8818 sz_strlcpy(packet.name, untranslated_name(&d->name));
8819 sz_strlcpy(packet.rule_name, rule_name_get(&d->name));
8820
8821 j = 0;
8822 requirement_vector_iterate(&d->reqs, preq) {
8823 packet.reqs[j++] = *preq;
8825 packet.reqs_count = j;
8826
8827 packet.frequency = d->frequency;
8828
8829 packet.effects = d->effects;
8830
8831 lsend_packet_ruleset_disaster(dest, &packet);
8833}
8834
8835/**********************************************************************/
8839static void send_ruleset_achievements(struct conn_list *dest)
8840{
8841 struct packet_ruleset_achievement packet;
8842
8844 packet.id = achievement_number(a);
8845
8846 sz_strlcpy(packet.name, untranslated_name(&a->name));
8847 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8848
8849 packet.type = a->type;
8850 packet.unique = a->unique;
8851 packet.value = a->value;
8852
8853 lsend_packet_ruleset_achievement(dest, &packet);
8855}
8856
8857/**********************************************************************/
8860static void send_ruleset_actions(struct conn_list *dest)
8861{
8862 struct packet_ruleset_action packet;
8863
8864 action_iterate(act) {
8865 struct action *paction = action_by_number(act);
8866
8867 packet.id = act;
8869 packet.quiet = action_by_number(act)->quiet;
8870
8871 packet.result = paction->result;
8872 packet.sub_results = paction->sub_results;
8873 packet.actor_consuming_always = paction->actor_consuming_always;
8874
8875 packet.act_kind = action_by_number(act)->actor_kind;
8876 packet.tgt_kind = action_by_number(act)->target_kind;
8878
8881 packet.blocked_by = action_by_number(act)->blocked_by;
8882
8883 lsend_packet_ruleset_action(dest, &packet);
8885}
8886
8887/**********************************************************************/
8891{
8892 int counter;
8893 struct packet_ruleset_action_enabler packet;
8894
8897
8898 counter = 0;
8899 requirement_vector_iterate(&enabler->actor_reqs, req) {
8900 packet.actor_reqs[counter++] = *req;
8902 packet.actor_reqs_count = counter;
8903
8904 counter = 0;
8905 requirement_vector_iterate(&enabler->target_reqs, req) {
8906 packet.target_reqs[counter++] = *req;
8908 packet.target_reqs_count = counter;
8909
8912}
8913
8914/**********************************************************************/
8919{
8920 int counter;
8921 int id;
8922 struct packet_ruleset_action_auto packet;
8923
8924 id = 0;
8926 packet.id = id++;
8927
8928 packet.cause = aperf->cause;
8929
8930 counter = 0;
8931 requirement_vector_iterate(&aperf->reqs, req) {
8932 packet.reqs[counter++] = *req;
8934 packet.reqs_count = counter;
8935
8936 for (counter = 0;
8937 /* Can't list more actions than all actions. */
8939 /* ACTION_NONE terminates the list. */
8940 && aperf->alternatives[counter] != ACTION_NONE;
8941 counter++) {
8942 packet.alternatives[counter] = aperf->alternatives[counter];
8943 }
8944 packet.alternatives_count = counter;
8945
8946 lsend_packet_ruleset_action_auto(dest, &packet);
8948}
8949
8950/**********************************************************************/
8954static void send_ruleset_trade_routes(struct conn_list *dest)
8955{
8956 struct packet_ruleset_trade packet;
8958
8959 for (type = TRT_NATIONAL; type < TRT_LAST; type++) {
8961
8962 packet.id = type;
8963 packet.trade_pct = set->trade_pct;
8964 packet.cancelling = set->cancelling;
8965 packet.bonus_type = set->bonus_type;
8966
8967 lsend_packet_ruleset_trade(dest, &packet);
8968 }
8969}
8970
8971/**********************************************************************/
8975static void send_ruleset_governments(struct conn_list *dest)
8976{
8977 struct packet_ruleset_government gov;
8979 int j;
8980
8982 /* Send one packet_government */
8983 gov.id = government_number(g);
8984
8985 j = 0;
8986 requirement_vector_iterate(&g->reqs, preq) {
8987 gov.reqs[j++] = *preq;
8989 gov.reqs_count = j;
8990
8991 sz_strlcpy(gov.name, untranslated_name(&g->name));
8992 sz_strlcpy(gov.rule_name, rule_name_get(&g->name));
8993 sz_strlcpy(gov.graphic_str, g->graphic_str);
8994 sz_strlcpy(gov.graphic_alt, g->graphic_alt);
8995 sz_strlcpy(gov.sound_str, g->sound_str);
8996 sz_strlcpy(gov.sound_alt, g->sound_alt);
8997 sz_strlcpy(gov.sound_alt2, g->sound_alt2);
8998 PACKET_STRVEC_COMPUTE(gov.helptext, g->helptext);
8999
9001
9002 /* Send one packet_government_ruler_title per ruler title. */
9004 const struct nation_type *pnation = ruler_title_nation(pruler_title);
9005
9006 title.gov = government_number(g);
9007 title.nation = pnation ? nation_number(pnation) : nation_count();
9008 sz_strlcpy(title.male_title,
9010 sz_strlcpy(title.female_title,
9015}
9016
9017/**********************************************************************/
9021static void send_ruleset_nations(struct conn_list *dest)
9022{
9025 struct packet_ruleset_nation packet;
9026 int i;
9027
9029 i = 0;
9034 i++;
9037
9039 i = 0;
9041 sz_strlcpy(groups_packet.groups[i],
9043 groups_packet.hidden[i] = pgroup->hidden;
9044 i++;
9047
9049 packet.id = nation_number(n);
9050 if (n->translation_domain == NULL) {
9051 packet.translation_domain[0] = '\0';
9052 } else {
9053 sz_strlcpy(packet.translation_domain, n->translation_domain);
9054 }
9055 sz_strlcpy(packet.adjective, untranslated_name(&n->adjective));
9056 sz_strlcpy(packet.rule_name, rule_name_get(&n->adjective));
9057 sz_strlcpy(packet.noun_plural, untranslated_name(&n->noun_plural));
9058 sz_strlcpy(packet.graphic_str, n->flag_graphic_str);
9059 sz_strlcpy(packet.graphic_alt, n->flag_graphic_alt);
9060
9061 i = 0;
9065 i++;
9067 packet.leader_count = i;
9068
9069 packet.style = style_number(n->style);
9070 packet.is_playable = n->is_playable;
9071 packet.barbarian_type = n->barb_type;
9072
9073 sz_strlcpy(packet.legend, n->legend);
9074
9075 i = 0;
9077 packet.sets[i++] = nation_set_number(pset);
9079 packet.nsets = i;
9080
9081 i = 0;
9083 packet.groups[i++] = nation_group_number(pgroup);
9085 packet.ngroups = i;
9086
9087 packet.init_government_id = n->init_government
9088 ? government_number(n->init_government) : government_count();
9089 fc_assert(ARRAY_SIZE(packet.init_techs) == ARRAY_SIZE(n->init_techs));
9090 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9091 if (n->init_techs[i] != A_LAST) {
9092 packet.init_techs[i] = n->init_techs[i];
9093 } else {
9094 break;
9095 }
9096 }
9097 packet.init_techs_count = i;
9098 fc_assert(ARRAY_SIZE(packet.init_units) == ARRAY_SIZE(n->init_units));
9099 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
9100 const struct unit_type *t = n->init_units[i];
9101 if (t) {
9102 packet.init_units[i] = utype_number(t);
9103 } else {
9104 break;
9105 }
9106 }
9107 packet.init_units_count = i;
9109 == ARRAY_SIZE(n->init_buildings));
9110 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9111 if (n->init_buildings[i] != B_LAST) {
9112 /* Impr_type_id to int */
9113 packet.init_buildings[i] = n->init_buildings[i];
9114 } else {
9115 break;
9116 }
9117 }
9118 packet.init_buildings_count = i;
9119
9120 lsend_packet_ruleset_nation(dest, &packet);
9122
9123 /* Send initial values of is_pickable */
9125}
9126
9127/**********************************************************************/
9131static void send_ruleset_styles(struct conn_list *dest)
9132{
9133 struct packet_ruleset_style packet;
9134
9135 styles_iterate(s) {
9136 packet.id = style_index(s);
9137 sz_strlcpy(packet.name, untranslated_name(&s->name));
9138 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
9139
9140 lsend_packet_ruleset_style(dest, &packet);
9142}
9143
9144/**********************************************************************/
9147static void send_ruleset_clauses(struct conn_list *dest)
9148{
9149 struct packet_ruleset_clause packet;
9150 int i;
9151
9152 for (i = 0; i < CLAUSE_COUNT; i++) {
9153 struct clause_info *info = clause_info_get(i);
9154 int j;
9155
9156 packet.type = i;
9157 packet.enabled = info->enabled;
9158
9159 j = 0;
9161 packet.giver_reqs[j++] = *preq;
9163 packet.giver_reqs_count = j;
9164
9165 j = 0;
9167 packet.receiver_reqs[j++] = *preq;
9169 packet.receiver_reqs_count = j;
9170
9171 lsend_packet_ruleset_clause(dest, &packet);
9172 }
9173}
9174
9175/**********************************************************************/
9179static void send_ruleset_multipliers(struct conn_list *dest)
9180{
9181 multipliers_iterate(pmul) {
9182 int j;
9183 struct packet_ruleset_multiplier packet;
9184
9185 packet.id = multiplier_number(pmul);
9186 packet.start = pmul->start;
9187 packet.stop = pmul->stop;
9188 packet.step = pmul->step;
9189 packet.def = pmul->def;
9190 packet.offset = pmul->offset;
9191 packet.factor = pmul->factor;
9192 packet.minimum_turns = pmul->minimum_turns;
9193
9194 sz_strlcpy(packet.name, untranslated_name(&pmul->name));
9195 sz_strlcpy(packet.rule_name, rule_name_get(&pmul->name));
9196
9197 j = 0;
9198 requirement_vector_iterate(&pmul->reqs, preq) {
9199 packet.reqs[j++] = *preq;
9201 packet.reqs_count = j;
9202
9203 PACKET_STRVEC_COMPUTE(packet.helptext, pmul->helptext);
9204
9205 lsend_packet_ruleset_multiplier(dest, &packet);
9207}
9208
9209/**********************************************************************/
9213static void send_ruleset_cities(struct conn_list *dest)
9214{
9216 int k, j;
9217
9218 for (k = 0; k < game.control.num_city_styles; k++) {
9219 city_p.style_id = k;
9220
9221 j = 0;
9223 city_p.reqs[j++] = *preq;
9225 city_p.reqs_count = j;
9226
9229 sz_strlcpy(city_p.graphic, city_styles[k].graphic);
9230 sz_strlcpy(city_p.graphic_alt, city_styles[k].graphic_alt);
9231 sz_strlcpy(city_p.citizens_graphic, city_styles[k].citizens_graphic);
9232
9234 }
9235}
9236
9237/**********************************************************************/
9241static void send_ruleset_musics(struct conn_list *dest)
9242{
9243 struct packet_ruleset_music packet;
9244
9246 int j;
9247
9248 packet.id = pmus->id;
9249
9250 sz_strlcpy(packet.music_peaceful, pmus->music_peaceful);
9251 sz_strlcpy(packet.music_combat, pmus->music_combat);
9252
9253 j = 0;
9255 packet.reqs[j++] = *preq;
9257 packet.reqs_count = j;
9258
9259 lsend_packet_ruleset_music(dest, &packet);
9261}
9262
9263/**********************************************************************/
9267static void send_ruleset_game(struct conn_list *dest)
9268{
9270 int i;
9271
9273
9274 /* Per unit veteran system definition. */
9275 misc_p.veteran_levels = game.veteran->levels;
9276
9277 for (i = 0; i < misc_p.veteran_levels; i++) {
9278 const struct veteran_level *vlevel = game.veteran->definitions + i;
9279
9280 sz_strlcpy(misc_p.veteran_name[i], untranslated_name(&vlevel->name));
9281 misc_p.power_fact[i] = vlevel->power_fact;
9282 misc_p.move_bonus[i] = vlevel->move_bonus;
9283 misc_p.base_raise_chance[i] = vlevel->base_raise_chance;
9284 misc_p.work_raise_chance[i] = vlevel->work_raise_chance;
9285 }
9286
9287 fc_assert(sizeof(misc_p.global_init_techs)
9288 == sizeof(game.rgame.global_init_techs));
9289 fc_assert(ARRAY_SIZE(misc_p.global_init_techs)
9291 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9293 misc_p.global_init_techs[i] = game.rgame.global_init_techs[i];
9294 } else {
9295 break;
9296 }
9297 }
9298 misc_p.global_init_techs_count = i;
9299
9300 fc_assert(ARRAY_SIZE(misc_p.global_init_buildings)
9302 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9304 /* Impr_type_id to int */
9305 misc_p.global_init_buildings[i] =
9307 } else {
9308 break;
9309 }
9310 }
9311 misc_p.global_init_buildings_count = i;
9312
9313 misc_p.default_specialist = DEFAULT_SPECIALIST;
9314
9316
9317 misc_p.background_red = game.plr_bg_color->r;
9318 misc_p.background_green = game.plr_bg_color->g;
9319 misc_p.background_blue = game.plr_bg_color->b;
9320
9322}
9323
9324/**********************************************************************/
9328static void send_ruleset_team_names(struct conn_list *dest)
9329{
9331
9333 const char *name = team_slot_defined_name(tslot);
9334
9335 if (NULL == name) {
9336 /* End of defined names. */
9337 break;
9338 }
9339
9341 sz_strlcpy(team_name_info_p.team_name, name);
9342
9345}
9346
9347/**********************************************************************/
9350static void notify_ruleset_fallback(const char *msg)
9351{
9353}
9354
9355/**********************************************************************/
9358bool load_rulesets(const char *restore, const char *alt, bool compat_mode,
9359 rs_conversion_logger logger,
9360 bool act, bool buffer_script, bool load_luadata)
9361{
9362 set_ruleset_compat_mode(compat_mode);
9363
9364 if (load_rulesetdir(game.server.rulesetdir, compat_mode, logger,
9365 act, buffer_script, load_luadata)) {
9367 return TRUE;
9368 }
9369
9370 if (alt != NULL) {
9371 if (load_rulesetdir(alt, compat_mode, logger, act, buffer_script,
9372 load_luadata)) {
9374
9376 return TRUE;
9377 }
9378 }
9379
9380 /* Fallback to previous one. */
9381 if (restore != NULL) {
9382 if (load_rulesetdir(restore, compat_mode, logger, act, buffer_script, TRUE)) {
9384
9385 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Keeping previous one."));
9386
9388
9389 /* We're in sane state as restoring previous ruleset succeeded,
9390 * but return failure to indicate that this is not what caller
9391 * wanted. */
9392 return FALSE;
9393 }
9394 }
9395
9397
9398 /* Fallback to default one, but not if that's what we tried already */
9402 /* We're in sane state as fallback ruleset loading succeeded,
9403 * but return failure to indicate that this is not what caller
9404 * wanted. */
9406
9407 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Switching to default one."));
9408
9409 return FALSE;
9410 }
9411 }
9412
9413#ifdef FREECIV_WEB
9414 log_normal(_("Cannot load any ruleset. Freeciv-web ruleset is available from "
9415 "https://github.com/freeciv/freeciv-web"));
9416#endif /* FREECIV_WEB */
9417
9418 /* Cannot load even default ruleset, we're in completely unusable state */
9420
9422}
9423
9424/**********************************************************************/
9428{
9429 if (file != NULL) {
9430 secfile_destroy(file);
9431 }
9432}
9433
9434/**********************************************************************/
9443
9444/**********************************************************************/
9448static bool load_rulesetdir(const char *rsdir, bool compat_mode,
9449 rs_conversion_logger logger,
9450 bool act, bool buffer_script, bool load_luadata)
9451{
9454 struct section_file *actionfile;
9455 bool ok = TRUE;
9457
9458 log_normal(_("Loading rulesets."));
9459
9461 compat_info.compat_mode = compat_mode;
9462 compat_info.log_cb = logger;
9463
9465 /* Reset the list of available player colors. */
9469
9470 if (script_buffer != NULL) {
9473 }
9474 if (parser_buffer != NULL) {
9477 }
9478
9479 server.playable_nations = 0;
9480
9482
9483 if (gamefile != NULL) {
9484 /* Needed here to fill compat_info. RSFORMAT_3_2 specific arrangement. */
9486 } else {
9487 ok = FALSE;
9488 }
9489
9491
9492 if (compat_info.version >= RSFORMAT_3_2) {
9494 } else {
9495 actionfile = NULL;
9496 }
9497
9498 buildfile = openload_ruleset_file("buildings", rsdir);
9499 govfile = openload_ruleset_file("governments", rsdir);
9501 terrfile = openload_ruleset_file("terrain", rsdir);
9506
9507 if (load_luadata) {
9509 } else {
9511 }
9512
9513 if (techfile == NULL
9514 || buildfile == NULL
9515 || govfile == NULL
9516 || unitfile == NULL
9517 || terrfile == NULL
9518 || stylefile == NULL
9519 || cityfile == NULL
9520 || nationfile == NULL
9521 || effectfile == NULL
9522 || (actionfile == NULL && (!compat_info.compat_mode || compat_info.version >= RSFORMAT_3_2))
9523 || gamefile == NULL) {
9524 ok = FALSE;
9525 }
9526
9527 if (ok) {
9528 /* Note: Keep load_game_names() first so that compat_info.version is
9529 * correctly initialized. (Currently handled above already) */
9538 }
9539
9540 if (ok) {
9541 /* 3.1 rulesets have no actions.ruleset. */
9542 if (compat_info.compat_mode && compat_info.version < RSFORMAT_3_2) {
9544 } else {
9546 }
9547 }
9548
9549 if (ok) {
9551 }
9552
9553 if (ok) {
9555 }
9556 if (ok) {
9558 }
9559 if (ok) {
9561 }
9562 if (ok) {
9564 }
9565 if (ok) {
9566 /* Terrain must precede nations and units */
9568 }
9569 if (ok) {
9571 }
9572 if (ok) {
9574 }
9575 if (ok) {
9577 }
9578 if (ok) {
9580 }
9581 if (ok) {
9583 }
9584
9585 if (ok) {
9586 /* Init nations we just loaded. */
9588
9589 /* Needed by role_unit_precalcs(). */
9591
9592 /* Prepare caches we want to sanity check. */
9596
9599 }
9600
9601 if (ok) {
9602 /* Only load settings for a sane ruleset */
9603 ok = settings_ruleset(gamefile, "settings", act,
9604 compat_info.compat_mode
9605 && compat_info.version < RSFORMAT_3_2);
9606
9607 if (ok) {
9609 }
9610 }
9611
9623
9624 if (extra_sections) {
9627 }
9628 if (base_sections) {
9631 }
9632 if (road_sections) {
9635 }
9636 if (resource_sections) {
9639 }
9640 if (terrain_sections) {
9643 }
9644
9645 if (ok) {
9647 }
9648
9649 if (ok) {
9650 char **buffer = buffer_script ? &script_buffer : NULL;
9651
9653
9655
9656 ok = (openload_script_file("script", rsdir, buffer, FALSE) == TRI_YES);
9657 }
9658
9659 if (ok) {
9660 enum fc_tristate pret;
9661 char **buffer = buffer_script ? &parser_buffer : NULL;
9662
9663 pret = openload_script_file("parser", rsdir, buffer, compat_info.compat_mode);
9664
9665 if (pret == TRI_MAYBE && buffer_script) {
9667 "-- This file is for lua-functionality for parsing luadata.txt\n-- of this ruleset.");
9668 }
9669
9670 ok = (pret != TRI_NO);
9671 }
9672
9673 if (ok && !buffer_script) {
9674 ok = (openload_script_file("default", rsdir, NULL, FALSE) == TRI_YES);
9675 }
9676
9677 if (ok && act) {
9678 /* Populate remaining caches. */
9685 ptype->unknown_move_cost = utype_unknown_move_cost(ptype);
9689
9690 /* Build advisors unit class cache corresponding to loaded rulesets */
9692 CALL_FUNC_EACH_AI(units_ruleset_init);
9693
9694 /* We may need to adjust the number of AI players
9695 * if the number of available nations changed. */
9697 }
9698
9699 return ok;
9700}
9701
9702/**********************************************************************/
9706{
9707 struct section_file *file;
9708 bool ok = TRUE;
9709
9711 if (file == NULL) {
9713 "Could not load game.ruleset:\n%s",
9714 secfile_error());
9715 ok = FALSE;
9716 }
9717 if (ok) {
9718 settings_ruleset(file, "settings", TRUE, FALSE);
9719 secfile_destroy(file);
9720 }
9721
9722 return ok;
9723}
9724
9725/**********************************************************************/
9728void send_rulesets(struct conn_list *dest)
9729{
9731
9732 /* ruleset_control also indicates to client that ruleset sending starts. */
9734
9735 /* Currently containing control-kind of data of nation sets and groups,
9736 * this too must be sent before any requirement vector may depend on
9737 * that data. */
9739
9740 send_ruleset_game(dest);
9750 send_ruleset_techs(dest);
9753 send_ruleset_units(dest);
9755 send_ruleset_extras(dest);
9756 send_ruleset_bases(dest);
9757 send_ruleset_roads(dest);
9760 send_ruleset_goods(dest);
9762 send_ruleset_styles(dest);
9764 send_ruleset_cities(dest);
9766 send_ruleset_musics(dest);
9767 send_ruleset_cache(dest);
9768
9769 /* Indicate client that all rulesets have now been sent. */
9771
9772 /* changed game settings will be send in
9773 * connecthand.c:establish_new_connection() */
9774
9776}
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:6421
void actions_rs_pre_san_gen(void)
Definition actions.c:1654
const char * action_min_range_ruleset_var_name(int act)
Definition actions.c:7116
const char * action_blocked_by_ruleset_var_name(const struct action *act)
Definition actions.c:7757
bool action_is_in_use(struct action *paction)
Definition actions.c:6398
const char * action_post_success_forced_ruleset_var_name(const struct action *act)
Definition actions.c:7933
struct action * action_by_rule_name(const char *name)
Definition actions.c:1840
const char * action_rule_name(const struct action *action)
Definition actions.c:1977
const char * action_actor_consuming_always_ruleset_var_name(action_id act)
Definition actions.c:7600
const char * action_max_range_ruleset_var_name(int act)
Definition actions.c:7276
const char * action_target_kind_ruleset_var_name(int act)
Definition actions.c:7445
void action_enabler_add(struct action_enabler *enabler)
Definition actions.c:2282
const char * action_ui_name_default(int act)
Definition actions.c:6773
struct action_enabler * action_enabler_new(void)
Definition actions.c:2236
bool action_enabler_possible_actor(const struct action_enabler *ae)
Definition actions.c:6342
struct action_enabler_list * action_enablers_for_action(action_id action)
Definition actions.c:2315
const char * action_ui_name_ruleset_var_name(int act)
Definition actions.c:6506
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:481
#define action_auto_perf_iterate_end
Definition actions.h:586
#define action_enablers_iterate_end
Definition actions.h:519
#define ACTION_AUTO_MOVED_ADJ
Definition actions.h:611
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:656
#define ACTION_AUTO_UPKEEP_GOLD
Definition actions.h:609
#define enabler_get_action_id(_enabler_)
Definition actions.h:434
static struct action * action_by_number(action_id act_id)
Definition actions.h:635
#define NUM_ACTIONS
Definition actions.h:315
#define ACTION_AUTO_ESCAPE_STACK
Definition actions.h:617
#define action_has_result(_act_, _res_)
Definition actions.h:431
#define ACTION_AUTO_ESCAPE_CITY
Definition actions.h:616
#define action_enabler_list_iterate_end
Definition actions.h:441
#define ACTION_DISTANCE_UNLIMITED
Definition actions.h:357
#define action_by_result_iterate_end
Definition actions.h:485
#define ACTION_AUTO_POST_WIPE_UNITS
Definition actions.h:618
#define ACTION_AUTO_UPKEEP_SHIELD
Definition actions.h:610
#define ACTION_AUTO_POST_BRIBE
Definition actions.h:612
#define action_iterate_end
Definition actions.h:465
#define action_enablers_iterate(_enabler_)
Definition actions.h:513
#define ACTION_AUTO_POST_ATTACK2
Definition actions.h:614
#define action_enabler_list_iterate(action_enabler_list, aenabler)
Definition actions.h:439
#define action_id(_act_)
Definition actions.h:661
#define action_iterate(_act_)
Definition actions.h:461
#define action_auto_perf_iterate(_act_perf_)
Definition actions.h:574
#define ACTION_AUTO_UPKEEP_FOOD
Definition actions.h:608
#define ACTION_AUTO_POST_ATTACK
Definition actions.h:613
#define ACTION_AUTO_POST_COLLECT_RANSOM
Definition actions.h:615
#define ACTION_NONE
Definition actions.h:311
int actres_min_range_default(enum action_result result)
Definition actres.c:373
int actres_max_range_default(enum action_result result)
Definition actres.c:462
enum action_target_kind actres_target_kind_default(enum action_result result)
Definition actres.c:763
void adv_units_ruleset_init(void)
Definition advruleset.c:33
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define str
Definition astring.c:76
#define n
Definition astring.c:77
Base_type_id base_number(const struct base_type *pbase)
Definition base.c:92
void base_type_init(struct extra_type *pextra, int idx)
Definition base.c:117
bool territory_claiming_base(const struct base_type *pbase)
Definition base.c:158
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
void city_styles_alloc(int num)
Definition city.c:3396
void city_production_caravan_shields_init(void)
Definition city.c:1778
const char * city_style_rule_name(const int style)
Definition city.c:1765
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
static const struct city struct citystyle * city_styles
Definition city.c:84
#define output_type_iterate(output)
Definition city.h:845
#define output_type_iterate_end
Definition city.h:851
static struct fc_sockaddr_list * list
Definition clinet.c:102
char * incite_cost
Definition comments.c:75
#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:732
void conn_list_compression_freeze(const struct conn_list *pconn_list)
Definition connection.c:720
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
#define log_deprecation(message,...)
struct clause_info * clause_info_get(enum clause_type type)
Definition diptreaty.c:276
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:80
#define disaster_type_iterate_end
Definition disaster.h:86
int int id
Definition editgui_g.h:28
struct @21::@22 reqs
void send_ruleset_cache(struct conn_list *dest)
Definition effects.c:610
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:1348
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:1359
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:1339
#define effect_list_iterate_end
Definition effects.h:406
#define effect_list_iterate(effect_list, peffect)
Definition effects.h:404
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:974
void set_user_extra_flag_name(enum extra_flag_id id, const char *name, const char *helptxt)
Definition extras.c:933
bool is_extra_caused_by_worker_action(const struct extra_type *pextra)
Definition extras.c:1032
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:861
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
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_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_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:678
#define MAX_DISASTER_TYPES
Definition fc_types.h:52
#define MAX_VET_LEVELS
Definition fc_types.h:49
@ ROCO_RAILROAD
Definition fc_types.h:1253
@ ROCO_NONE
Definition fc_types.h:1253
@ ROCO_RIVER
Definition fc_types.h:1253
@ ROCO_ROAD
Definition fc_types.h:1253
#define MAX_GRANARY_INIS
Definition fc_types.h:72
#define MAX_NUM_NATIONS
Definition fc_types.h:60
#define MAX_NUM_BUILDING_LIST
Definition fc_types.h:46
#define MAX_NUM_REQS
Definition fc_types.h:410
#define MAX_GOODS_TYPES
Definition fc_types.h:51
#define EC_NATURAL_DEFENSIVE
Definition fc_types.h:1116
#define EC_SPECIAL
Definition fc_types.h:1114
int action_id
Definition fc_types.h:389
#define SP_MAX
Definition fc_types.h:409
#define EC_NONE
Definition fc_types.h:1113
#define EC_NOT_AGGRESSIVE
Definition fc_types.h:1117
#define EC_DEFENSIVE
Definition fc_types.h:1115
#define MAX_CALENDAR_FRAGMENTS
Definition fc_types.h:62
#define MAX_NUM_TECH_CLASSES
Definition fc_types.h:63
#define MAX_NUM_LEADERS
Definition fc_types.h:56
#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:126
#define MAX_ACHIEVEMENT_TYPES
Definition fc_types.h:53
#define MAX_LEN_NAME
Definition fc_types.h:66
#define MAX_NUM_TECH_LIST
Definition fc_types.h:44
#define MAX_LEN_CITYNAME
Definition fc_types.h:67
#define MAX_COUNTERS
Definition fc_types.h:106
#define UCL_LAST
Definition fc_types.h:417
#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:512
void game_ruleset_free(void)
Definition game.c:561
struct world wld
Definition game.c:63
#define RS_DEFAULT_RANSOM_GOLD
Definition game.h:872
#define RS_DEFAULT_GRANARY_FOOD_INI
Definition game.h:821
#define RS_DEFAULT_CIVIL_WAR_UNHAPPY
Definition game.h:858
#define RS_DEFAULT_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:864
#define RS_MIN_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:802
#define RS_MAX_TECH_UPKEEP_DIVIDER
Definition game.h:884
#define RS_MIN_ILLNESS_POLLUTION_PCT
Definition game.h:788
#define RS_DEFAULT_NUKE_POP_LOSS_PCT
Definition game.h:861
#define RS_MAX_BORDER_RADIUS_SQ_CITY
Definition game.h:795
#define RS_DEFAULT_BASE_POLLUTION
Definition game.h:844
#define RS_MIN_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:784
#define RS_MAX_ILLNESS_BASE_FACTOR
Definition game.h:777
#define RS_DEFAULT_INCITE_TOTAL_FCT
Definition game.h:817
#define RS_DEFAULT_ILLNESS_BASE_FACTOR
Definition game.h:775
#define RS_DEFAULT_NEG_YEAR_LABEL
Definition game.h:771
#define RS_MIN_NUKE_POP_LOSS_PCT
Definition game.h:862
#define RS_MIN_INCITE_IMPROVEMENT_FCT
Definition game.h:810
#define RS_MIN_FOOD_COST
Definition game.h:854
#define RS_MIN_BASE_BRIBE_COST
Definition game.h:869
#define RS_MAX_NUKE_POP_LOSS_PCT
Definition game.h:863
#define RS_DEFAULT_INCITE_IMPROVEMENT_FCT
Definition game.h:809
#define RS_MAX_INCITE_IMPROVEMENT_FCT
Definition game.h:811
#define RS_MIN_RANSOM_GOLD
Definition game.h:873
#define RS_ACTION_NO_MAX_DISTANCE
Definition game.h:896
#define RS_DEFAULT_BASE_BRIBE_COST
Definition game.h:868
#define RS_MAX_INCITE_BASE_COST
Definition game.h:807
#define RS_DEFAULT_TECH_UPKEEP_DIVIDER
Definition game.h:882
#define RS_DEFAULT_HAPPY_COST
Definition game.h:849
#define RS_MIN_UPGRADE_VETERAN_LOSS
Definition game.h:879
#define RS_MIN_ILLNESS_MIN_SIZE
Definition game.h:780
#define RS_DEFAULT_POISON_EMPTIES_FOOD_STOCK
Definition game.h:886
#define RS_DEFAULT_GRANARY_FOOD_INC
Definition game.h:823
#define RS_DEFAULT_ILLNESS_ON
Definition game.h:773
#define RS_MAX_FOOD_COST
Definition game.h:855
#define RS_MAX_HAPPY_COST
Definition game.h:851
#define GAME_DEFAULT_CELEBRATESIZE
Definition game.h:502
#define RS_MIN_ILLNESS_BASE_FACTOR
Definition game.h:776
#define RS_DEFAULT_STEAL_MAP_REVEALS_CITIES
Definition game.h:887
#define RS_MIN_TECH_UPKEEP_DIVIDER
Definition game.h:883
#define RS_MAX_RANSOM_GOLD
Definition game.h:874
#define RS_MIN_HAPPY_COST
Definition game.h:850
#define RS_MIN_BORDER_RADIUS_SQ_CITY
Definition game.h:794
#define GAME_DEFAULT_RULESETDIR
Definition game.h:676
#define RS_DEFAULT_CIVIL_WAR_CELEB
Definition game.h:857
#define RS_MIN_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:865
#define RS_MAX_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:803
#define RS_DEFAULT_UPGRADE_VETERAN_LOSS
Definition game.h:878
#define RS_MAX_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:866
#define RS_MAX_INCITE_UNIT_FCT
Definition game.h:815
#define RS_MIN_VIS_RADIUS_SQ
Definition game.h:841
#define RS_DEFAULT_CALENDAR_SKIP_0
Definition game.h:791
#define RS_MAX_ILLNESS_MIN_SIZE
Definition game.h:781
#define RS_DEFAULT_CITY_RADIUS_SQ
Definition game.h:836
#define GAME_DEFAULT_START_YEAR
Definition game.h:743
#define RS_MAX_BORDER_SIZE_EFFECT
Definition game.h:799
#define RS_DEFAULT_BORDER_SIZE_EFFECT
Definition game.h:797
#define RS_MAX_BASE_BRIBE_COST
Definition game.h:870
#define RS_MIN_INCITE_BASE_COST
Definition game.h:806
#define RS_DEFAULT_PILLAGE_SELECT
Definition game.h:876
#define RS_MIN_CITY_RADIUS_SQ
Definition game.h:837
#define RS_MIN_CITY_CENTER_OUTPUT
Definition game.h:828
#define RS_MAX_GRANARY_FOOD_INC
Definition game.h:825
#define RS_MAX_CITY_CENTER_OUTPUT
Definition game.h:829
#define RS_MAX_CITY_RADIUS_SQ
Definition game.h:838
#define RS_DEFAULT_POS_YEAR_LABEL
Definition game.h:769
#define RS_MIN_INCITE_UNIT_FCT
Definition game.h:814
#define RS_MIN_BORDER_SIZE_EFFECT
Definition game.h:798
#define RS_DEFAULT_VIS_RADIUS_SQ
Definition game.h:840
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:801
#define RS_DEFAULT_TIRED_ATTACK
Definition game.h:860
#define RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS
Definition game.h:888
#define RS_MAX_ILLNESS_POLLUTION_PCT
Definition game.h:789
#define RS_DEFAULT_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:783
#define RS_DEFAULT_FOOD_COST
Definition game.h:853
#define RS_DEFAULT_INCITE_UNIT_FCT
Definition game.h:813
#define RS_MAX_INCITE_TOTAL_FCT
Definition game.h:819
#define RS_DEFAULT_INCITE_BASE_COST
Definition game.h:805
#define GAME_DEFAULT_ANGRYCITIZEN
Definition game.h:393
#define RS_DEFAULT_CITY_CENTER_OUTPUT
Definition game.h:827
#define RS_MIN_INCITE_TOTAL_FCT
Definition game.h:818
#define RS_DEFAULT_ILLNESS_POLLUTION_PCT
Definition game.h:787
#define RS_MAX_UPGRADE_VETERAN_LOSS
Definition game.h:880
static void set_ruleset_compat_mode(bool active)
Definition game.h:357
#define RS_MAX_VIS_RADIUS_SQ
Definition game.h:842
#define RS_MIN_GRANARY_FOOD_INC
Definition game.h:824
#define RS_MAX_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:785
#define RS_DEFAULT_ILLNESS_MIN_SIZE
Definition game.h:779
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY
Definition game.h:793
const struct nation_type * ruler_title_nation(const struct ruler_title *pruler_title)
Definition government.c:365
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:325
const char * ruler_title_female_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:383
Government_type_id government_count(void)
Definition government.c:71
const char * ruler_title_male_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:374
void governments_alloc(int num)
Definition government.c:529
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
const struct ruler_title_hash * government_ruler_titles(const struct government *pgovern)
Definition government.c:314
Government_type_id government_index(const struct government *pgovern)
Definition government.c:82
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
#define governments_iterate(NAME_pgov)
Definition government.h:124
#define G_LAST
Definition government.h:48
#define ruler_titles_iterate(ARG_hash, NAME_rule_title)
Definition government.h:38
#define ruler_titles_iterate_end
Definition government.h:41
#define governments_iterate_end
Definition government.h:127
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_NEVER
Definition improvement.h:44
#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:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define MAX_LEN_LOG_LINE
Definition log.h:26
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_do_output_for_level(level)
Definition log.h:89
#define log_debug(message,...)
Definition log.h:115
#define log_normal(message,...)
Definition log.h:107
log_level
Definition log.h:28
@ LOG_ERROR
Definition log.h:30
@ LOG_FATAL
Definition log.h:29
#define log_error(message,...)
Definition log.h:103
struct terrain_misc terrain_control
Definition map.c:69
#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:105
void init_move_fragments(void)
Definition movement.c:927
#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:1047
const char * nation_group_untranslated_name(const struct nation_group *pgroup)
Definition nation.c:1069
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1021
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_count(void)
Definition nation.c:507
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:486
struct nation_group * nation_group_new(const char *name)
Definition nation.c:960
bool nation_leader_is_male(const struct nation_leader *pleader)
Definition nation.c:290
struct nation_set * nation_set_new(const char *set_name, const char *set_rule_name, const char *set_description)
Definition nation.c:716
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:475
struct nation_city * nation_city_new(struct nation_type *pnation, const char *name)
Definition nation.c:342
const struct nation_leader_list * nation_leaders(const struct nation_type *pnation)
Definition nation.c:230
const char * nation_set_untranslated_name(const struct nation_set *pset)
Definition nation.c:797
bool is_nation_playable(const struct nation_type *nation)
Definition nation.c:200
int nation_set_number(const struct nation_set *pset)
Definition nation.c:708
void nation_city_set_terrain_preference(struct nation_city *pncity, const struct terrain *pterrain, enum nation_city_preference prefer)
Definition nation.c:390
void nation_city_set_river_preference(struct nation_city *pncity, enum nation_city_preference prefer)
Definition nation.c:402
bool nation_is_in_set(const struct nation_type *pnation, const struct nation_set *pset)
Definition nation.c:837
const char * nation_set_description(const struct nation_set *pset)
Definition nation.c:828
int nation_set_count(void)
Definition nation.c:691
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:498
const char * nation_leader_name(const struct nation_leader *pleader)
Definition nation.c:281
int nation_group_count(void)
Definition nation.c:935
const char * nation_set_rule_name(const struct nation_set *pset)
Definition nation.c:807
struct nation_leader * nation_leader_new(struct nation_type *pnation, const char *name, bool is_male)
Definition nation.c:239
void nation_group_set_hidden(struct nation_group *pgroup, bool hidden)
Definition nation.c:1037
void nations_alloc(int num)
Definition nation.c:622
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:211
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:952
#define nation_leader_list_iterate(leaderlist, pleader)
Definition nation.h:57
#define nation_sets_iterate_end
Definition nation.h:305
#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:301
#define nations_iterate_end
Definition nation.h:336
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:333
#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:311
#define nation_groups_iterate_end
Definition nation.h:315
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_COMPUTE(str, strvec)
Definition packets.h:185
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_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_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 city_list * cities
Definition packhand.c:119
int len
Definition packhand.c:127
void send_nation_availability(struct conn_list *dest, bool nationset_change)
Definition plrhand.c:2641
void playercolor_free(void)
Definition plrhand.c:3341
void playercolor_init(void)
Definition plrhand.c:3332
int playercolor_count(void)
Definition plrhand.c:3380
void playercolor_add(struct rgbcolor *prgbcolor)
Definition plrhand.c:3360
void count_playable_nations(void)
Definition plrhand.c:2598
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:50
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,...)
const char * entry_name(const struct entry *pentry)
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,...)
struct entry * section_entry_by_name(const struct section *psection, const char *name)
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
#define secfile_entry_ignore_by_path(_sfile_, _path_)
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
const char * rscompat_req_range_3_2(struct rscompat_info *compat, const char *type, const char *old_range)
Definition rscompat.c:471
int add_user_extra_flags_3_2(int start)
Definition rscompat.c:564
const char * rscompat_action_ui_name_3_2(struct rscompat_info *compat, int act_id)
Definition rscompat.c:783
bool rscompat_terrain_extra_rmtime_3_2(struct section_file *file, const char *tsection, struct terrain *pterrain)
Definition rscompat.c:713
bool rscompat_names(struct rscompat_info *info)
Definition rscompat.c:330
void rscompat_postprocess(struct rscompat_info *info)
Definition rscompat.c:386
int rscompat_check_capabilities(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:66
void rscompat_extra_adjust_3_2(struct extra_type *pextra)
Definition rscompat.c:603
void rscompat_enablers_add_obligatory_hard_reqs(void)
Definition rscompat.c:286
const char * rscompat_action_rule_name_3_2(struct rscompat_info *compat, const char *orig)
Definition rscompat.c:753
void rscompat_req_adjust_3_2(const struct rscompat_info *compat, const char **ptype, const char **pname, bool *ppresent, const char *sec_name)
Definition rscompat.c:498
enum impr_genus_id rscompat_genus_3_2(struct rscompat_info *compat, const bv_impr_flags flags, enum impr_genus_id old_genus)
Definition rscompat.c:455
void rscompat_action_enabler_adjust_3_2(struct rscompat_info *compat, struct action_enabler *enabler, const char *orig_name)
Definition rscompat.c:768
const char * rscompat_extra_rmcause_3_2(struct extra_type *pextra, const char *old_name)
Definition rscompat.c:577
void rscompat_init_info(struct rscompat_info *info)
Definition rscompat.c:57
bool rscompat_check_cap_and_version(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:131
bool sanity_check_ruleset_data(struct rscompat_info *compat)
Definition rssanity.c:878
bool autoadjust_ruleset_data(void)
Definition rssanity.c:1576
#define check_cityname(name)
Definition ruleset.c:116
static int ruleset_purge_redundant_reqs_enablers(void)
Definition ruleset.c:423
static void ruleset_load_traits(struct trait_limits *out, struct section_file *file, const char *secname, const char *field_prefix)
Definition ruleset.c:1313
static bool load_rulesetdir(const char *rsdir, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleset.c:9448
#define STYLE_SECTION_PREFIX
Definition ruleset.c:98
static bool lookup_terrain(struct section_file *file, const char *entry, const char *filename, struct terrain *pthis, struct terrain **result, bool null_acceptable)
Definition ruleset.c:1214
static bool load_ruleset_veteran(struct section_file *file, const char *path, struct veteran_system **vsystem, char *err, size_t err_len)
Definition ruleset.c:1989
static bool load_terrain_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2855
static bool load_style_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5755
int ruleset_purge_unused_entities(void)
Definition ruleset.c:313
#define MUSICSTYLE_SECTION_PREFIX
Definition ruleset.c:91
static char * road_sections
Definition ruleset.c:127
static bool load_ruleset_governments(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:4460
#define MULTIPLIER_SECTION_PREFIX
Definition ruleset.c:112
static struct requirement_vector reqs_list
Definition ruleset.c:129
static void send_ruleset_techs(struct conn_list *dest)
Definition ruleset.c:8295
#define section_strlcpy(dst, src)
Definition ruleset.c:121
static bool load_action_range(struct section_file *file, action_id act)
Definition ruleset.c:6485
#define check_name(name)
Definition ruleset.c:115
static void send_ruleset_units(struct conn_list *dest)
Definition ruleset.c:8110
static void send_ruleset_governments(struct conn_list *dest)
Definition ruleset.c:8975
static bool load_action_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1482
static struct extra_type * lookup_resource(const char *filename, const char *name, const char *jsection)
Definition ruleset.c:1193
static struct section_file * openload_luadata_file(const char *rsdir)
Definition ruleset.c:626
static bool load_ruleset_techs(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1620
static bool purge_unused_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleset.c:327
void rulesets_deinit(void)
Definition ruleset.c:9438
static bool load_action_ui_name(struct section_file *file, int act, const char *entry_name, const char *compat_name)
Definition ruleset.c:6422
static void send_ruleset_resources(struct conn_list *dest)
Definition ruleset.c:8580
static bool load_ruleset_buildings(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2727
static char * terrain_sections
Definition ruleset.c:124
static bool lookup_building_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleset.c:1045
static void nullcheck_secfile_destroy(struct section_file *file)
Definition ruleset.c:9427
static void send_ruleset_clauses(struct conn_list *dest)
Definition ruleset.c:9147
static void send_ruleset_game(struct conn_list *dest)
Definition ruleset.c:9267
char * parser_buffer
Definition ruleset.c:209
#define NATION_SECTION_PREFIX
Definition ruleset.c:97
static bool load_ruleset_effects(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:6210
static bool lookup_cbonus_list(struct combat_bonus_list *list, struct section_file *file, const char *sec, const char *sub)
Definition ruleset.c:797
static void send_ruleset_nations(struct conn_list *dest)
Definition ruleset.c:9021
static void send_ruleset_roads(struct conn_list *dest)
Definition ruleset.c:8737
static int ruleset_purge_unused_enablers(void)
Definition ruleset.c:244
#define UEFF_SECTION_PREFIX
Definition ruleset.c:92
static bool is_on_allowed_list(const char *name, const char **list, size_t len)
Definition ruleset.c:4852
static void send_ruleset_tech_classes(struct conn_list *dest)
Definition ruleset.c:8277
static void send_ruleset_action_enablers(struct conn_list *dest)
Definition ruleset.c:8890
static void send_ruleset_control(struct conn_list *dest)
Definition ruleset.c:4658
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 ruleset.c:9358
#define GOODS_SECTION_PREFIX
Definition ruleset.c:104
void ruleset_error_real(rs_conversion_logger logger, const char *file, const char *function, int line, enum log_level level, const char *format,...)
Definition ruleset.c:215
#define TERRAIN_SECTION_PREFIX
Definition ruleset.c:106
static struct section_file * openload_ruleset_file(const char *whichset, const char *rsdir)
Definition ruleset.c:571
static void send_ruleset_musics(struct conn_list *dest)
Definition ruleset.c:9241
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 ruleset.c:1264
int ruleset_purge_redundant_reqs(void)
Definition ruleset.c:490
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 ruleset.c:6384
static char * base_sections
Definition ruleset.c:126
#define DISASTER_SECTION_PREFIX
Definition ruleset.c:109
static void send_ruleset_goods(struct conn_list *dest)
Definition ruleset.c:8777
static const char name_too_long[]
Definition ruleset.c:119
bool reload_rulesets_settings(void)
Definition ruleset.c:9705
static struct strvec * lookup_strvec(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleset.c:1173
#define CITYSTYLE_SECTION_PREFIX
Definition ruleset.c:90
static bool lookup_tech(struct section_file *file, struct advance **result, const char *prefix, const char *entry, const char *filename, const char *description)
Definition ruleset.c:856
static bool load_game_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1352
static void send_ruleset_counters(struct conn_list *dest)
Definition ruleset.c:8386
static void send_ruleset_specialists(struct conn_list *dest)
Definition ruleset.c:8249
#define ADVANCE_SECTION_PREFIX
Definition ruleset.c:87
#define EFFECT_SECTION_PREFIX
Definition ruleset.c:93
static void send_ruleset_action_auto_performers(struct conn_list *dest)
Definition ruleset.c:8918
static bool load_government_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:4378
static void send_ruleset_team_names(struct conn_list *dest)
Definition ruleset.c:9328
static void send_ruleset_cities(struct conn_list *dest)
Definition ruleset.c:9213
static bool lookup_building(struct section_file *file, const char *prefix, const char *entry, struct impr_type **result, const char *filename, const char *description)
Definition ruleset.c:888
static bool purge_redundant_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleset.c:412
static char * lookup_string(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleset.c:1153
static const char * check_leader_names(struct nation_type *pnation)
Definition ruleset.c:4696
#define ACTION_ENABLER_SECTION_PREFIX
Definition ruleset.c:111
#define BASE_SECTION_PREFIX
Definition ruleset.c:101
static int ruleset_purge_redundant_reqs_effects(void)
Definition ruleset.c:461
static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir, char **buffer, bool optional)
Definition ruleset.c:599
char * get_parser_buffer(void)
Definition ruleset.c:562
static bool load_building_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2646
#define EXTRA_SECTION_PREFIX
Definition ruleset.c:100
void send_rulesets(struct conn_list *dest)
Definition ruleset.c:9728
#define CLAUSE_SECTION_PREFIX
Definition ruleset.c:99
static bool lookup_unit_list(struct section_file *file, const char *prefix, const char *entry, struct unit_type **output, const char *filename)
Definition ruleset.c:921
static char * resource_sections
Definition ruleset.c:123
#define UNIT_SECTION_PREFIX
Definition ruleset.c:108
#define ACHIEVEMENT_SECTION_PREFIX
Definition ruleset.c:110
static bool load_ruleset_cities(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5995
static bool load_ruleset_styles(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5816
static struct government * lookup_government(struct section_file *file, const char *entry, const char *filename, struct government *fallback)
Definition ruleset.c:1128
static bool load_ruleset_units(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2110
char * script_buffer
Definition ruleset.c:208
static bool load_action_blocked_by_list(struct section_file *file, const char *filename, struct action *paction)
Definition ruleset.c:6549
static void send_ruleset_styles(struct conn_list *dest)
Definition ruleset.c:9131
#define NATION_GROUP_SECTION_PREFIX
Definition ruleset.c:96
static char * extra_sections
Definition ruleset.c:125
#define RULES_SUFFIX
Definition ruleset.c:84
struct requirement_vector * lookup_req_list(struct section_file *file, struct rscompat_info *compat, const char *sec, const char *sub, const char *rfor)
Definition ruleset.c:654
static void send_ruleset_disasters(struct conn_list *dest)
Definition ruleset.c:8809
static bool purge_duplicate_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleset.c:367
static bool lookup_tech_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleset.c:981
#define MAX_SECTION_LABEL
Definition ruleset.c:120
#define BUILDING_SECTION_PREFIX
Definition ruleset.c:89
static bool load_ruleset_game(struct section_file *file, bool act, struct rscompat_info *compat)
Definition ruleset.c:6664
static bool load_nation_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:4716
static void send_ruleset_achievements(struct conn_list *dest)
Definition ruleset.c:8839
#define SCRIPT_SUFFIX
Definition ruleset.c:85
static void send_ruleset_bases(struct conn_list *dest)
Definition ruleset.c:8715
static bool load_ruleset_terrain(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:3191
static int ruleset_purge_unused_effects(void)
Definition ruleset.c:290
static bool load_action_actor_consuming_always(struct section_file *file, action_id act)
Definition ruleset.c:6532
static bool load_action_post_success_force(struct section_file *file, const char *filename, int performer_slot, struct action *paction)
Definition ruleset.c:6593
static bool load_tech_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1502
#define SPECIALIST_SECTION_PREFIX
Definition ruleset.c:105
#define COUNTER_SECTION_PREFIX
Definition ruleset.c:113
static bool load_action_kind(struct section_file *file, action_id act)
Definition ruleset.c:6510
static void send_ruleset_multipliers(struct conn_list *dest)
Definition ruleset.c:9179
char * get_script_buffer(void)
Definition ruleset.c:554
static void send_ruleset_actions(struct conn_list *dest)
Definition ruleset.c:8860
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 ruleset.c:4868
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 ruleset.c:5894
static bool load_ruleset_nations(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5038
static bool load_action_auto_actions(struct section_file *file, struct action_auto_perf *auto_perf, const char *actions_path, const char *filename)
Definition ruleset.c:5937
static void send_ruleset_unit_classes(struct conn_list *dest)
Definition ruleset.c:8062
#define TECH_CLASS_SECTION_PREFIX
Definition ruleset.c:88
#define RESOURCE_SECTION_PREFIX
Definition ruleset.c:103
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 ruleset.c:1097
static void send_ruleset_extras(struct conn_list *dest)
Definition ruleset.c:8599
#define rs_sanity_veteran(_path, _entry, _i, _condition, _action)
static void send_ruleset_terrain(struct conn_list *dest)
Definition ruleset.c:8473
#define GOVERNMENT_SECTION_PREFIX
Definition ruleset.c:94
static bool load_unit_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1831
static void send_ruleset_trade_routes(struct conn_list *dest)
Definition ruleset.c:8954
static bool load_ruleset_actions(struct section_file *file, struct section_file *gamefile, struct rscompat_info *compat)
Definition ruleset.c:7732
static void notify_ruleset_fallback(const char *msg)
Definition ruleset.c:9350
static bool lookup_bv_actions(struct section_file *file, const char *filename, bv_actions *target, const char *path)
Definition ruleset.c:6630
static void send_ruleset_buildings(struct conn_list *dest)
Definition ruleset.c:8407
#define UNIT_CLASS_SECTION_PREFIX
Definition ruleset.c:107
static bool ruleset_load_names(struct name_translation *pname, const char *domain, struct section_file *file, const char *sec_name)
Definition ruleset.c:1290
#define ROAD_SECTION_PREFIX
Definition ruleset.c:102
static const char * valid_ruleset_filename(const char *subdir, const char *name, const char *extension, bool optional)
Definition ruleset.c:509
static bool load_action_range_max(struct section_file *file, action_id act)
Definition ruleset.c:6444
static bool load_muuk_as_action_auto(struct section_file *file, struct action_auto_perf *auto_perf, const char *item, const char *filename)
Definition ruleset.c:5973
#define NATION_SET_SECTION_PREFIX
Definition ruleset.c:95
#define RS_DEFAULT_CONVERT_SPEED
Definition ruleset.h:119
#define RS_DEFAULT_UBUILD_NAT
Definition ruleset.h:118
#define RS_DEFAULT_DAMAGE_REDUCES_BOMBARD_RATE
Definition ruleset.h:105
#define RS_DEFAULT_TECH_TRADE_LOSS_HOLES
Definition ruleset.h:82
#define RS_DEFAULT_TECH_COST_STYLE
Definition ruleset.h:88
#define RS_DEFAULT_EXTRA_APPEARANCE
Definition ruleset.h:99
#define RS_DEFAULT_TECH_PARASITE_HOLES
Definition ruleset.h:83
#define GAME_DEFAULT_ACH_VALUE
Definition ruleset.h:76
#define RS_DEFAULT_TECH_TRADE_HOLES
Definition ruleset.h:81
#define RS_DEFAULT_CULTURE_VIC_POINTS
Definition ruleset.h:92
#define RS_DEFAULT_CULTURE_MIGRATION_PML
Definition ruleset.h:94
void(* rs_conversion_logger)(const char *msg)
Definition ruleset.h:40
#define RS_DEFAULT_SMALL_WONDER_VISIBILITY
Definition ruleset.h:107
#define ruleset_error(logger, level, format,...)
Definition ruleset.h:57
#define RS_DEFAULT_ONLY_KILLING_VETERAN
Definition ruleset.h:102
#define RS_DEFAULT_TECH_LOSS_HOLES
Definition ruleset.h:84
#define RS_DEFAULT_HISTORY_INTEREST_PML
Definition ruleset.h:95
#define RS_DEFAULT_TECH_UPKEEP_STYLE
Definition ruleset.h:90
#define RS_DEFAULT_GOODS_SELECTION
Definition ruleset.h:97
#define RS_DEFAULT_PYTHAGOREAN_DIAGONAL
Definition ruleset.h:85
#define RS_DEFAULT_TECH_STEAL_HOLES
Definition ruleset.h:80
#define RS_MIN_MIN_TECH_COST
Definition ruleset.h:114
#define GAME_DEFAULT_ACH_UNIQUE
Definition ruleset.h:75
#define RS_MAX_BASE_TECH_COST
Definition ruleset.h:111
#define RS_DEFAULT_COMBAT_ODDS_SCALED_VETERANCY
Definition ruleset.h:104
#define RS_DEFAULT_MUUK_FOOD_WIPE
Definition ruleset.h:77
#define RS_DEFAULT_MUUK_GOLD_WIPE
Definition ruleset.h:78
#define RS_DEFAULT_BASE_TECH_COST
Definition ruleset.h:109
#define RSFORMAT_3_2
Definition ruleset.h:36
#define RS_DEFAULT_NATIONALITY
Definition ruleset.h:117
#define GAME_DEFAULT_CHANGABLE_TAX
Definition ruleset.h:72
#define RS_DEFAULT_MUUK_SHIELD_WIPE
Definition ruleset.h:79
#define RS_DEFAULT_GOLD_UPKEEP_STYLE
Definition ruleset.h:87
#define GAME_DEFAULT_ADDTOSIZE
Definition ruleset.h:71
#define RS_DEFAULT_ONLY_REAL_FIGHT_VETERAN
Definition ruleset.h:103
#define RS_DEFAULT_EXTRA_DISAPPEARANCE
Definition ruleset.h:100
#define RS_MAX_MIN_TECH_COST
Definition ruleset.h:115
#define RS_DEFAULT_MIN_TECH_COST
Definition ruleset.h:113
#define GAME_DEFAULT_VISION_REVEAL_TILES
Definition ruleset.h:73
#define RS_DEFAULT_CULTURE_VIC_LEAD
Definition ruleset.h:93
#define RS_DEFAULT_TECH_LEAKAGE
Definition ruleset.h:89
#define GAME_DEFAULT_DISASTER_FREQ
Definition ruleset.h:74
#define RS_MIN_BASE_TECH_COST
Definition ruleset.h:110
static struct compatibility compat[]
Definition savecompat.c:105
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:4376
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:495
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1101
void remove_leading_trailing_spaces(char *s)
Definition shared.c:444
const struct strvec * get_data_dirs(void)
Definition shared.c:893
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_number(const Specialist_type_id id)
Definition specialist.c:100
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
#define DEFAULT_SPECIALIST
Definition specialist.h:43
const char * aifill(int amount)
Definition srv_main.c:2465
void update_nations_with_startpos(void)
Definition srv_main.c:2270
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:395
int max_distance
Definition actions.h:378
bool quiet
Definition actions.h:385
char ui_name[MAX_LEN_NAME]
Definition actions.h:381
bv_action_sub_results sub_results
Definition actions.h:366
enum action_actor_kind actor_kind
Definition actions.h:368
bv_actions blocked_by
Definition actions.h:389
enum action_target_kind target_kind
Definition actions.h:369
int min_distance
Definition actions.h:378
struct advance * require[AR_SIZE]
Definition tech.h:132
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:285
int named_teams
Definition game.h:297
size_t as_count
Definition game.h:296
const char ** allowed_govs
Definition game.h:288
int upgrade_veteran_loss
Definition game.h:203
struct rgbcolor * plr_bg_color
Definition game.h:103
int incite_total_factor
Definition game.h:154
int init_vis_radius_sq
Definition game.h:156
bool vision_reveal_tiles
Definition game.h:204
char * description_file
Definition game.h:284
struct packet_ruleset_control control
Definition game.h:83
char * ruleset_summary
Definition game.h:84
char ** nc_agovs
Definition game.h:289
int base_incite_cost
Definition game.h:138
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:136
char rulesetdir[MAX_LEN_NAME]
Definition game.h:242
int start_year
Definition game.h:195
int incite_improvement_factor
Definition game.h:153
struct section_file * luadata
Definition game.h:250
char ** embedded_nations
Definition game.h:286
int global_init_buildings[MAX_NUM_BUILDING_LIST]
Definition game.h:111
struct trait_limits default_traits[TRAIT_COUNT]
Definition game.h:277
char ** nc_astyles
Definition game.h:295
const char ** allowed_terrains
Definition game.h:291
struct civ_game::@31::@35::@40 ruledit
char * ruleset_description
Definition game.h:85
size_t ag_count
Definition game.h:290
const char ** allowed_styles
Definition game.h:294
struct civ_game::@31::@35 server
char ** nc_aterrs
Definition game.h:292
size_t embedded_nations_count
Definition game.h:287
int incite_unit_factor
Definition game.h:155
char * ruleset_capabilities
Definition game.h:86
struct civ_game::@30 rgame
int ransom_gold
Definition game.h:179
size_t at_count
Definition game.h:293
struct veteran_system * veteran
Definition game.h:101
struct packet_calendar_info calendar
Definition game.h:90
struct government * default_government
Definition game.h:93
struct government * government_during_revolution
Definition game.h:94
struct civ_map::@42::@44 server
bool ocean_resources
Definition map_types.h:106
struct requirement_vector receiver_reqs
Definition diptreaty.h:59
struct requirement_vector giver_reqs
Definition diptreaty.h:58
bool enabled
Definition diptreaty.h:57
enum unit_type_flag_id flag
Definition unittype.h:467
enum combat_bonus_type type
Definition unittype.h:468
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:169
char * legend
Definition nation.h:107
enum barbarian_type barb_type
Definition nation.h:110
char positive_year_label[MAX_LEN_NAME]
char negative_year_label[MAX_LEN_NAME]
char calendar_fragment_name[MAX_CALENDAR_FRAGMENTS][MAX_LEN_NAME]
bool tech_steal_allow_holes
enum gameloss_style gameloss_style
enum goods_selection_method goods_selection
Government_type_id government_during_revolution_id
enum gold_upkeep_style gold_upkeep_style
bool damage_reduces_bombard_rate
int nuke_defender_survival_chance_pct
enum tech_upkeep_style tech_upkeep_style
bool tech_trade_loss_allow_holes
int granary_food_ini[MAX_GRANARY_INIS]
enum free_tech_method free_tech_method
bool steal_maps_reveals_all_cities
bool only_real_fight_makes_veteran
int low_firepower_pearl_harbour
enum tech_leakage_style tech_leakage
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
int civil_war_bonus_celebrating
Government_type_id default_government_id
int min_city_center_output[O_LAST]
char rule_name[MAX_LEN_NAME]
enum achievement_type type
char name[MAX_LEN_NAME]
action_id alternatives[MAX_NUM_ACTIONS]
struct requirement reqs[MAX_NUM_REQS]
enum action_auto_perf_cause cause
struct requirement actor_reqs[MAX_NUM_REQS]
struct requirement target_reqs[MAX_NUM_REQS]
enum action_sub_target_kind sub_tgt_kind
enum action_actor_kind act_kind
bv_action_sub_results sub_results
char ui_name[MAX_LEN_NAME]
enum action_target_kind tgt_kind
enum action_result result
enum base_gui_type gui_type
char helptext[MAX_LEN_PACKET]
struct requirement obs_reqs[MAX_NUM_REQS]
char soundtag_alt[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
enum impr_genus_id genus
char name[MAX_LEN_NAME]
char soundtag[MAX_LEN_NAME]
char soundtag_alt2[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char graphic_alt2[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
enum clause_type type
struct requirement receiver_reqs[MAX_NUM_REQS]
struct requirement giver_reqs[MAX_NUM_REQS]
char preferred_soundset[MAX_LEN_NAME]
char version[MAX_LEN_NAME]
char preferred_tileset[MAX_LEN_NAME]
char alt_dir[MAX_LEN_NAME]
char preferred_musicset[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
enum counter_behaviour behaviour
enum counter_target type
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char helptext[MAX_LEN_PACKET]
char rule_name[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
bv_disaster_effects effects
char name[MAX_LEN_NAME]
char helptxt[MAX_LEN_PACKET]
bv_unit_classes native_to
char rmact_gfx_alt2[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
char graphic_alt[MAX_LEN_NAME]
char act_gfx_alt2[MAX_LEN_NAME]
struct requirement disappearance_reqs[MAX_NUM_REQS]
bv_extra_flags flags
char act_gfx_alt[MAX_LEN_NAME]
char activity_gfx[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
enum extra_unit_seen_type eus
struct requirement appearance_reqs[MAX_NUM_REQS]
char name[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
char rmact_gfx_alt[MAX_LEN_NAME]
char rmact_gfx[MAX_LEN_NAME]
struct requirement rmreqs[MAX_NUM_REQS]
char helptext[MAX_LEN_PACKET]
char helptext[MAX_LEN_PACKET]
bv_goods_flags flags
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
char helptxt[MAX_LEN_PACKET]
char name[MAX_LEN_NAME]
Multiplier_type_id id
struct requirement reqs[MAX_NUM_REQS]
char rule_name[MAX_LEN_NAME]
char helptext[MAX_LEN_PACKET]
char music_combat[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
char music_peaceful[MAX_LEN_NAME]
int init_techs[MAX_NUM_TECH_LIST]
char leader_name[MAX_NUM_LEADERS][MAX_LEN_NAME]
char noun_plural[MAX_LEN_NAME]
char adjective[MAX_LEN_NAME]
Impr_type_id init_buildings[MAX_NUM_BUILDING_LIST]
Unit_type_id init_units[MAX_NUM_UNIT_LIST]
bool leader_is_male[MAX_NUM_LEADERS]
char translation_domain[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
Government_type_id init_government_id
int groups[MAX_NUM_NATION_GROUPS]
enum barbarian_type barbarian_type
int sets[MAX_NUM_NATION_SETS]
char graphic_alt[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char legend[MAX_LEN_MSG]
bv_road_flags flags
int tile_incr_const[O_LAST]
enum road_gui_type gui_type
bv_max_extras integrates
enum road_compat compat
enum road_move_mode move_mode
int tile_bonus[O_LAST]
int tile_incr[O_LAST]
struct requirement first_reqs[MAX_NUM_REQS]
char rule_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
Specialist_type_id id
char helptext[MAX_LEN_PACKET]
char short_name[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
char plural_name[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char text[MAX_LEN_CONTENT]
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char helptxt[MAX_LEN_PACKET]
char name[MAX_LEN_NAME]
struct requirement research_reqs[MAX_NUM_REQS]
char graphic_str[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
bv_tech_flags flags
char helptext[MAX_LEN_PACKET]
char helptxt[MAX_LEN_PACKET]
int extra_removal_times[MAX_EXTRA_TYPES]
Terrain_type_id transform_result
int resource_freq[MAX_EXTRA_TYPES]
char helptext[MAX_LEN_PACKET]
Resource_type_id resources[MAX_EXTRA_TYPES]
bv_terrain_flags flags
char graphic_str[MAX_LEN_NAME]
bv_unit_classes native_to
Terrain_type_id cultivate_result
Terrain_type_id plant_result
char name[MAX_LEN_NAME]
int road_output_incr_pct[O_LAST]
char graphic_alt[MAX_LEN_NAME]
char graphic_alt2[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
enum trade_route_illegal_cancelling cancelling
enum trade_route_bonus_type bonus_type
char helptxt[MAX_LEN_PACKET]
char rule_name[MAX_LEN_NAME]
bv_unit_class_flags flags
char name[MAX_LEN_NAME]
char helptext[MAX_LEN_PACKET]
char helptxt[MAX_LEN_PACKET]
char graphic_alt[MAX_LEN_NAME]
enum vision_layer vlayer
enum transp_def_type tp_defense
char rule_name[MAX_LEN_NAME]
int power_fact[MAX_VET_LEVELS]
char name[MAX_LEN_NAME]
char graphic_alt2[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
char sound_fight_alt[MAX_LEN_NAME]
bv_unit_classes disembarks
bv_unit_classes cargo
bv_unit_type_flags flags
char sound_move_alt[MAX_LEN_NAME]
bv_unit_classes targets
struct requirement build_reqs[MAX_NUM_REQS]
int base_raise_chance[MAX_VET_LEVELS]
int work_raise_chance[MAX_VET_LEVELS]
char sound_fight[MAX_LEN_NAME]
bv_unit_classes embarks
char veteran_name[MAX_VET_LEVELS][MAX_LEN_NAME]
char sound_move[MAX_LEN_NAME]
char helptext[MAX_LEN_PACKET]
bv_unit_type_roles roles
int move_bonus[MAX_VET_LEVELS]
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:902
struct veteran_level * definitions
Definition unittype.h:497
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
void styles_alloc(int count)
Definition style.c:36
struct music_style * music_style_by_number(int id)
Definition style.c:171
int style_number(const struct nation_style *pstyle)
Definition style.c:68
void music_styles_alloc(int count)
Definition style.c:133
int style_index(const struct nation_style *pstyle)
Definition style.c:78
#define music_styles_iterate(_p)
Definition style.h:72
#define music_styles_iterate_end
Definition style.h:79
#define styles_iterate(_p)
Definition style.h:46
#define styles_iterate_end
Definition style.h:52
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
bool fc_isspace(char c)
Definition support.c:1254
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:836
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:900
char fc_tolower(char c)
Definition support.c:1287
#define sz_strlcpy(dest, src)
Definition support.h:195
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:146
#define fc__attribute(x)
Definition support.h:99
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct team_slot * team_slot_by_number(int team_id)
Definition team.c:175
const char * team_slot_defined_name(const struct team_slot *tslot)
Definition team.c:277
int team_slot_index(const struct team_slot *tslot)
Definition team.c:138
int team_slot_count(void)
Definition team.c:112
void team_slot_set_defined_name(struct team_slot *tslot, const char *team_name)
Definition team.c:288
#define team_slots_iterate_end
Definition team.h:77
#define team_slots_iterate(_tslot)
Definition team.h:72
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
const char * tech_flag_id_name_cb(enum tech_flag_id flag)
Definition tech.c:423
void set_user_tech_flag_name(enum tech_flag_id id, const char *name, const char *helptxt)
Definition tech.c:394
struct advance * valid_advance(struct advance *padvance)
Definition tech.c:152
void techs_precalc_data(void)
Definition tech.c:225
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
const char * tech_flag_helptxt(enum tech_flag_id id)
Definition tech.c:435
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
struct tech_class * tech_class_by_rule_name(const char *name)
Definition tech.c:351
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define tech_class_index(_ptclass_)
Definition tech.h:193
#define A_NEVER
Definition tech.h:51
#define tech_class_iterate_end
Definition tech.h:204
#define MAX_NUM_USER_TECH_FLAGS
Definition tech.h:108
#define advance_iterate_all_end
Definition tech.h:279
@ AR_TWO
Definition tech.h:112
@ AR_ROOT
Definition tech.h:113
@ AR_ONE
Definition tech.h:111
#define advance_iterate_all(_p)
Definition tech.h:278
static Tech_type_id advance_count(void)
Definition tech.h:170
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:275
#define tech_class_iterate(_p)
Definition tech.h:198
#define advance_iterate_end
Definition tech.h:276
#define A_LAST
Definition tech.h:45
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
Terrain_type_id terrain_count(void)
Definition terrain.c:118
const char * terrain_flag_id_name_cb(enum terrain_flag_id flag)
Definition terrain.c:817
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:138
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:156
const char * terrain_flag_helptxt(enum terrain_flag_id id)
Definition terrain.c:829
struct resource_type * resource_type_init(struct extra_type *pextra)
Definition terrain.c:272
void set_user_terrain_flag_name(enum terrain_flag_id id, const char *name, const char *helptxt)
Definition terrain.c:788
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:147
#define RESOURCE_FREQUENCY_MAXIMUM
Definition terrain.h:209
#define terrain_type_iterate(_p)
Definition terrain.h:373
#define T_NONE
Definition terrain.h:56
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:195
#define terrain_type_iterate_end
Definition terrain.h:379
#define RESOURCE_NONE_IDENTIFIER
Definition terrain.h:47
#define RESOURCE_NULL_IDENTIFIER
Definition terrain.h:46
#define RESOURCE_FREQUENCY_MINIMUM
Definition terrain.h:207
#define MAX_NUM_TERRAINS
Definition terrain.h:64
#define T_FIRST
Definition terrain.h:60
#define MAX_NUM_USER_TER_FLAGS
Definition terrain.h:152
#define terrain_resources_iterate_end
Definition terrain.h:401
#define terrain_resources_iterate(pterrain, _res, _freq)
Definition terrain.h:392
#define RESOURCE_FREQUENCY_DEFAULT
Definition terrain.h:208
#define ACTIVITY_FACTOR
Definition tile.h:165
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:2756
const char * unit_class_flag_helptxt(enum unit_class_flag_id id)
Definition unittype.c:1854
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1767
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:199
void unit_type_action_cache_init(void)
Definition unittype.c:931
void set_unit_type_caches(struct unit_type *ptype)
Definition unittype.c:2815
void role_unit_precalcs(void)
Definition unittype.c:2175
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:2685
Unit_type_id utype_count(void)
Definition unittype.c:80
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2625
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1578
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2597
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1641
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1784
const char * unit_type_flag_helptxt(enum unit_type_flag_id id)
Definition unittype.c:1917
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
void set_user_unit_class_flag_name(enum unit_class_flag_id id, const char *name, const char *helptxt)
Definition unittype.c:1812
struct veteran_system * veteran_system_new(int count)
Definition unittype.c:2654
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2468
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:371
void set_user_unit_type_flag_name(enum unit_type_flag_id id, const char *name, const char *helptxt)
Definition unittype.c:1876
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:766
#define utype_class(_t_)
Definition unittype.h:749
#define combat_bonus_list_iterate_end
Definition unittype.h:482
#define L_FIRST
Definition unittype.h:349
#define combat_bonus_list_iterate(bonuslist, pbonus)
Definition unittype.h:480
#define unit_tech_reqs_iterate_end
Definition unittype.h:881
#define unit_class_iterate(_p)
Definition unittype.h:908
#define unit_tech_reqs_iterate(_utype_, _p)
Definition unittype.h:875
#define MAX_NUM_USER_UNIT_FLAGS
Definition unittype.h:332
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
#define UTYF_LAST_USER_FLAG
Definition unittype.h:331
#define unit_type_iterate(_p)
Definition unittype.h:855
#define U_LAST
Definition unittype.h:40
#define uclass_index(_c_)
Definition unittype.h:742
#define unit_class_iterate_end
Definition unittype.h:915
#define unit_type_iterate_end
Definition unittype.h:862
#define MAX_NUM_USER_UCLASS_FLAGS
Definition unittype.h:128