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);
208 int def, int min, int max,
209 const char *path, ...)
211
214
215/**********************************************************************/
220 const char *file, const char *function,
222 const char *format, ...)
223{
224 va_list args;
225 char buf[MAX_LEN_LOG_LINE];
226
227 if (logger == NULL && !log_do_output_for_level(level)) {
228 return;
229 }
230
231 va_start(args, format);
232 if (logger != NULL) {
233 fc_vsnprintf(buf, sizeof(buf), format, args);
234 logger(buf);
235 } else {
236 vdo_log(file, function, line, FALSE, level, buf, sizeof(buf), format, args);
237 }
238 va_end(args);
239
240 if (LOG_FATAL >= level) {
242 }
243}
244
245/**********************************************************************/
249{
250 int purged = 0;
251
252 action_iterate(act_id) {
253 struct action *paction = action_by_number(act_id);
254
256 == 0) {
257 /* Not relevant. */
258 continue;
259 }
260
261 /* Impossible hard requirement. */
263 /* Make sure that all action enablers are disabled. */
265 ae) {
266 ae->ruledit_disabled = TRUE;
267 purged++;
269
270 log_normal("Purged all action enablers for %s",
272 }
273
274 /* Impossible requirement vector requirement. */
276 ae) {
277 if (!ae->ruledit_disabled
279 || req_vec_is_impossible_to_fulfill(&ae->target_reqs))) {
280 ae->ruledit_disabled = TRUE;
281 purged++;
282 log_normal("Purged unused action enabler for %s",
284 }
287
288 return purged;
289}
290
291/**********************************************************************/
295{
296 int purged = 0;
297 enum effect_type type;
298
303 eft->rulesave.do_not_save = TRUE;
304 purged++;
305 log_normal("Purged unused effect for %s",
306 effect_type_name(eft->type));
307 }
309 }
310
311 return purged;
312}
313
314/**********************************************************************/
318{
319 int purged = 0;
320
323
324 return purged;
325}
326
327/**********************************************************************/
332 const char *msg)
333{
334 struct req_vec_problem *problem;
335 bool result;
336
338 reqs);
339
340 if (problem == NULL) {
341 /* No problem. */
342 return FALSE;
343 }
344
345 if (problem->num_suggested_solutions == 0) {
346 /* No solution. */
348 return FALSE;
349 }
350
351 if (problem->num_suggested_solutions == 1
352 && problem->suggested_solutions[0].operation == RVCO_REMOVE) {
353 /* Remove !present req that never is there. */
354 log_normal("%s", msg);
355 result = req_vec_change_apply(&problem->suggested_solutions[0],
358 return result;
359 }
360
361 /* Not handled. Don't know what this is. */
362 fc_assert(problem->num_suggested_solutions == 1);
364 return FALSE;
365}
366
367/**********************************************************************/
372 const char *msg)
373{
374 struct req_vec_problem *problem;
375 bool result;
376
378 reqs);
379
380 if (problem == NULL) {
381 /* No problem. */
382 return FALSE;
383 }
384
385 if (problem->num_suggested_solutions == 0) {
386 /* No solution. */
388 return FALSE;
389 }
390
391 if (problem->num_suggested_solutions == 2
392 && problem->suggested_solutions[0].operation == RVCO_REMOVE
393 && problem->suggested_solutions[1].operation == RVCO_REMOVE
394 && are_requirements_equal(&problem->suggested_solutions[0].req,
395 &problem->suggested_solutions[1].req)) {
396 /* Simple duplication is handled. */
397 log_normal("%s", msg);
398 result = req_vec_change_apply(&problem->suggested_solutions[1],
401 return result;
402 }
403
404 /* Requirements of different kinds making each other redundant isn't
405 * supported yet. It could be done by always removing the most general
406 * requirement. So unit type is kept when redundant with unit flag, unit
407 * class and unit class flag etc. */
409 return FALSE;
410}
411
412/**********************************************************************/
417 const char *msg)
418{
419 return (purge_unused_req_vec(reqs, msg)
421}
422
423/**********************************************************************/
428{
429 int purged = 0;
430
431 action_iterate(act_id) {
432 struct action *paction = action_by_number(act_id);
433 char actor_reqs[MAX_LEN_NAME * 2];
434 char target_reqs[MAX_LEN_NAME * 2];
435
436 /* Error log text */
437 fc_snprintf(actor_reqs, sizeof(actor_reqs),
438 "Purged redundant requirement in"
439 " %s in action enabler for %s",
440 "actor_reqs", action_rule_name(paction));
441 fc_snprintf(target_reqs, sizeof(target_reqs),
442 "Purged redundant requirement in"
443 " %s in action enabler for %s",
444 "target_reqs", action_rule_name(paction));
445
446 /* Do the purging. */
448 ae) {
449 while (!ae->ruledit_disabled
450 && (purge_redundant_req_vec(&ae->actor_reqs, actor_reqs)
451 || purge_redundant_req_vec(&ae->target_reqs,
452 target_reqs))) {
453 purged++;
454 }
457
458 return purged;
459}
460
461/**********************************************************************/
466{
467 int purged = 0;
468 enum effect_type type;
469
472 char msg[MAX_LEN_NAME * 2];
473
474 /* Error log text */
475 fc_snprintf(msg, sizeof(msg),
476 "Purged redundant requirement in effect of type %s",
478
479 /* Do the purging. */
481 while (purge_redundant_req_vec(&eft->reqs, msg)) {
482 purged++;
483 }
485 }
486
487 return purged;
488}
489
490/**********************************************************************/
495{
496 int purged = 0;
497
500
501 if (purged > 0) {
502 /* An unused requirement may be an obligatory hard requirement. */
504 }
505
506 return purged;
507}
508
509/**********************************************************************/
513static const char *valid_ruleset_filename(const char *subdir,
514 const char *name,
515 const char *extension,
516 bool optional)
517{
518 char filename[512];
519 const char *dfilename;
520
522
523 fc_snprintf(filename, sizeof(filename), "%s" DIR_SEPARATOR "%s.%s",
525 log_verbose("Trying \"%s\".", filename);
526 dfilename = fileinfoname(get_data_dirs(), filename);
527 if (dfilename) {
528 return dfilename;
529 }
530
531 fc_snprintf(filename, sizeof(filename), "default" DIR_SEPARATOR "%s.%s", name, extension);
532 log_verbose("Trying \"%s\": default ruleset directory.", filename);
533 dfilename = fileinfoname(get_data_dirs(), filename);
534 if (dfilename) {
535 return dfilename;
536 }
537
538 fc_snprintf(filename, sizeof(filename), "%s_%s.%s",
540 log_verbose("Trying \"%s\": alternative ruleset filename syntax.",
541 filename);
542 dfilename = fileinfoname(get_data_dirs(), filename);
543 if (dfilename) {
544 return dfilename;
545 } else if (!optional) {
547 /* TRANS: message about an installation error. */
548 _("Could not find a readable \"%s.%s\" ruleset file."),
549 name, extension);
550 }
551
552 return NULL;
553}
554
555/**********************************************************************/
559{
560 return script_buffer;
561}
562
563/**********************************************************************/
567{
568 return parser_buffer;
569}
570
571/**********************************************************************/
575static struct section_file *openload_ruleset_file(const char *whichset,
576 const char *rsdir)
577{
578 char sfilename[512];
581 struct section_file *secfile;
582
583 if (dfilename == NULL) {
584 return NULL;
585 }
586
587 /* Need to save a copy of the filename for following message, since
588 section_file_load() may call datafilename() for includes. */
590 secfile = secfile_load(sfilename, FALSE);
591
592 if (secfile == NULL) {
593 ruleset_error(NULL, LOG_ERROR, "Could not load ruleset '%s':\n%s",
595 }
596
597 return secfile;
598}
599
600/**********************************************************************/
603static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir,
604 char **buffer, bool optional)
605{
608
609 if (dfilename == NULL) {
610 return optional ? TRI_MAYBE : TRI_NO;
611 }
612
613 if (buffer == NULL) {
615 ruleset_error(NULL, LOG_ERROR, "\"%s\": could not load ruleset script.",
616 dfilename);
617
618 return TRI_NO;
619 }
620 } else {
622 }
623
624 return TRI_YES;
625}
626
627/**********************************************************************/
630static struct section_file *openload_luadata_file(const char *rsdir)
631{
632 struct section_file *secfile;
633 char sfilename[512];
634 const char *dfilename = valid_ruleset_filename(rsdir, "luadata",
635 "txt", TRUE);
636
637 if (dfilename == NULL) {
638 return NULL;
639 }
640
641 /* Need to save a copy of the filename for following message, since
642 section_file_load() may call datafilename() for includes. */
644 secfile = secfile_load(sfilename, FALSE);
645
646 if (secfile == NULL) {
647 ruleset_error(NULL, LOG_ERROR, "Could not load luadata '%s':\n%s",
649 }
650
651 return secfile;
652}
653
654/**********************************************************************/
659 struct rscompat_info *compat,
660 const char *sec,
661 const char *sub,
662 const char *rfor)
663{
664 const char *type, *name;
665 int j;
666 const char *filename;
667
668 filename = secfile_name(file);
669
671
672 for (j = 0; (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
673 sec, sub, j)); j++) {
674 char buf[MAX_LEN_NAME];
675 const char *range;
676 bool survives, present, quiet;
677 struct entry *pentry;
678 struct requirement req;
679
680 if (!(pentry = secfile_entry_lookup(file, "%s.%s%d.name",
681 sec, sub, j))) {
683
684 return NULL;
685 }
686 name = NULL;
687 switch (entry_type_get(pentry)) {
688 case ENTRY_BOOL:
689 {
690 bool val;
691
692 if (entry_bool_get(pentry, &val)) {
693 fc_snprintf(buf, sizeof(buf), "%d", val);
694 name = buf;
695 }
696 }
697 break;
698 case ENTRY_INT:
699 {
700 int val;
701
702 if (entry_int_get(pentry, &val)) {
703 fc_snprintf(buf, sizeof(buf), "%d", val);
704 name = buf;
705 }
706 }
707 break;
708 case ENTRY_STR:
710 break;
711 case ENTRY_FLOAT:
714 "\"%s\": trying to have an floating point entry as a requirement name in '%s.%s%d'.",
715 filename, sec, sub, j);
716 break;
719 break;
722 break;
723 case ENTRY_ILLEGAL:
725 break;
726 }
727 if (NULL == name) {
729 "\"%s\": error in handling requirement name for '%s.%s%d'.",
730 filename, sec, sub, j);
731 return NULL;
732 }
733
734 if (!(range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j))) {
736
737 return NULL;
738 }
739
740 if (compat->compat_mode) {
742 }
743
744 survives = FALSE;
745 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.survives",
746 sec, sub, j))
749 "\"%s\": invalid boolean value for survives for "
750 "'%s.%s%d'.", filename, sec, sub, j);
751 }
752
753 present = TRUE;
754 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.present",
755 sec, sub, j))
758 "\"%s\": invalid boolean value for present for "
759 "'%s.%s%d'.", filename, sec, sub, j);
760 }
761 quiet = FALSE;
762 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.quiet",
763 sec, sub, j))
764 && !entry_bool_get(pentry, &quiet)) {
766 "\"%s\": invalid boolean value for quiet for "
767 "'%s.%s%d'.", filename, sec, sub, j);
768 }
769
770 if (compat->compat_mode) {
772 }
773
775 if (req.source.kind == universals_n_invalid()) {
777 "\"%s\" [%s] has invalid or unknown req: "
778 "\"%s\" \"%s\".",
779 filename, sec, type, name);
780
781 return NULL;
782 }
783
785 }
786
787 if (j > MAX_NUM_REQS) {
789 "Too many (%d) requirements for %s. Max is %d",
790 j, rfor, MAX_NUM_REQS);
791
792 return NULL;
793 }
794
795 return &reqs_list;
796}
797
798/**********************************************************************/
802 struct section_file *file,
803 const char *sec,
804 const char *sub)
805{
806 const char *flag;
807 int j;
808 const char *filename;
809 bool success = TRUE;
810
811 filename = secfile_name(file);
812
813 for (j = 0; (flag = secfile_lookup_str_default(file, NULL, "%s.%s%d.flag",
814 sec, sub, j)); j++) {
815 struct combat_bonus *bonus = fc_malloc(sizeof(*bonus));
816 const char *type;
817
819 if (!unit_type_flag_id_is_valid(bonus->flag)) {
820 log_error("\"%s\": unknown flag name \"%s\" in '%s.%s'.",
821 filename, flag, sec, sub);
822 FC_FREE(bonus);
823 success = FALSE;
824 continue;
825 }
826 type = secfile_lookup_str(file, "%s.%s%d.type", sec, sub, j);
828 if (!combat_bonus_type_is_valid(bonus->type)) {
829 log_error("\"%s\": unknown bonus type \"%s\" in '%s.%s'.",
830 filename, type, sec, sub);
831 FC_FREE(bonus);
832 success = FALSE;
833 continue;
834 }
835 if (!secfile_lookup_int(file, &bonus->value, "%s.%s%d.value",
836 sec, sub, j)) {
837 log_error("\"%s\": failed to get value from '%s.%s%d'.",
838 filename, sec, sub, j);
839 FC_FREE(bonus);
840 success = FALSE;
841 continue;
842 }
844 "%s.%s%d.quiet",
845 sec, sub, j);
847 }
848
849 return success;
850}
851
852/**********************************************************************/
860static bool lookup_tech(struct section_file *file,
861 struct advance **result,
862 const char *prefix, const char *entry,
863 const char *filename,
864 const char *description)
865{
866 const char *sval;
867
868 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
869 if (!sval || !strcmp(sval, "Never")) {
870 *result = A_NEVER;
871 } else {
872 *result = advance_by_rule_name(sval);
873
874 if (A_NEVER == *result) {
876 "\"%s\" %s %s: couldn't match \"%s\".",
877 filename, (description ? description : prefix), entry, sval);
878 return FALSE;
879 }
880 }
881
882 return TRUE;
883}
884
885/**********************************************************************/
892static bool lookup_building(struct section_file *file,
893 const char *prefix, const char *entry,
894 struct impr_type **result,
895 const char *filename,
896 const char *description)
897{
898 const char *sval;
899 bool ok = TRUE;
900
901 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
902 if (!sval || strcmp(sval, "None") == 0) {
903 *result = B_NEVER;
904 } else {
906
907 if (B_NEVER == *result) {
909 "\"%s\" %s %s: couldn't match \"%s\".",
910 filename, (description ? description : prefix), entry, sval);
911 ok = FALSE;
912 }
913 }
914
915 return ok;
916}
917
918/**********************************************************************/
925static bool lookup_unit_list(struct section_file *file, const char *prefix,
926 const char *entry,
927 struct unit_type **output,
928 const char *filename)
929{
930 const char **slist;
931 size_t nval;
932 int i;
933 bool ok = TRUE;
934
935 /* pre-fill with NULL: */
936 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
937 output[i] = NULL;
938 }
939 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
940 if (nval == 0) {
941 /* 'No vector' is considered same as empty vector */
942 if (slist != NULL) {
943 free(slist);
944 }
945 return TRUE;
946 }
947 if (nval > MAX_NUM_UNIT_LIST) {
949 "\"%s\": string vector %s.%s too long (%d, max %d)",
950 filename, prefix, entry, (int) nval, MAX_NUM_UNIT_LIST);
951 ok = FALSE;
952 } else if (nval == 1 && strcmp(slist[0], "") == 0) {
953 free(slist);
954 return TRUE;
955 }
956 if (ok) {
957 for (i = 0; i < nval; i++) {
958 const char *sval = slist[i];
960
961 if (!punittype) {
963 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
964 filename, prefix, entry, i, sval);
965 ok = FALSE;
966 break;
967 }
968 output[i] = punittype;
969 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
971 }
972 }
973 free(slist);
974
975 return ok;
976}
977
978/**********************************************************************/
985static bool lookup_tech_list(struct section_file *file, const char *prefix,
986 const char *entry, int *output,
987 const char *filename)
988{
989 const char **slist;
990 size_t nval;
991 int i;
992 bool ok = TRUE;
993
994 /* pre-fill with A_LAST: */
995 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
996 output[i] = A_LAST;
997 }
998 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
999 if (slist == NULL || nval == 0) {
1000 return TRUE;
1001 } else if (nval > MAX_NUM_TECH_LIST) {
1003 "\"%s\": string vector %s.%s too long (%d, max %d)",
1004 filename, prefix, entry, (int) nval, MAX_NUM_TECH_LIST);
1005 ok = FALSE;
1006 }
1007
1008 if (ok) {
1009 if (nval == 1 && strcmp(slist[0], "") == 0) {
1010 FC_FREE(slist);
1011 return TRUE;
1012 }
1013 for (i = 0; i < nval && ok; i++) {
1014 const char *sval = slist[i];
1016
1017 if (NULL == padvance) {
1019 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1020 filename, prefix, entry, i, sval);
1021 ok = FALSE;
1022 }
1023 if (!valid_advance(padvance)) {
1025 "\"%s\" %s.%s (%d): \"%s\" is removed.",
1026 filename, prefix, entry, i, sval);
1027 ok = FALSE;
1028 }
1029
1030 if (ok) {
1031 output[i] = advance_number(padvance);
1032 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
1034 }
1035 }
1036 }
1037 FC_FREE(slist);
1038
1039 return ok;
1040}
1041
1042/**********************************************************************/
1049static bool lookup_building_list(struct section_file *file,
1050 const char *prefix, const char *entry,
1051 int *output, const char *filename)
1052{
1053 const char **slist;
1054 size_t nval;
1055 int i;
1056 bool ok = TRUE;
1057
1058 /* pre-fill with B_LAST: */
1059 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
1060 output[i] = B_LAST;
1061 }
1062 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
1065 "\"%s\": string vector %s.%s too long (%d, max %d)",
1066 filename, prefix, entry, (int) nval, MAX_NUM_BUILDING_LIST);
1067 ok = FALSE;
1068 } else if (nval == 0 || (nval == 1 && strcmp(slist[0], "") == 0)) {
1069 if (slist != NULL) {
1070 FC_FREE(slist);
1071 }
1072 return TRUE;
1073 }
1074 if (ok) {
1075 for (i = 0; i < nval; i++) {
1076 const char *sval = slist[i];
1077 struct impr_type *pimprove = improvement_by_rule_name(sval);
1078
1079 if (NULL == pimprove) {
1081 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1082 filename, prefix, entry, i, sval);
1083 ok = FALSE;
1084 break;
1085 }
1086 output[i] = improvement_number(pimprove);
1087 log_debug("%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
1088 }
1089 }
1090 free(slist);
1091
1092 return ok;
1093}
1094
1095/**********************************************************************/
1101static bool lookup_unit_type(struct section_file *file,
1102 const char *prefix,
1103 const char *entry,
1104 const struct unit_type **result,
1105 const char *filename,
1106 const char *description)
1107{
1108 const char *sval;
1109
1110 sval = secfile_lookup_str_default(file, "None", "%s.%s", prefix, entry);
1111
1112 if (strcmp(sval, "None") == 0) {
1113 *result = NULL;
1114 } else {
1115 *result = unit_type_by_rule_name(sval);
1116 if (*result == NULL) {
1118 "\"%s\" %s %s: couldn't match \"%s\".",
1119 filename, (description ? description : prefix), entry, sval);
1120
1121 return FALSE;
1122 }
1123 }
1124
1125 return TRUE;
1126}
1127
1128/**********************************************************************/
1132static struct government *lookup_government(struct section_file *file,
1133 const char *entry,
1134 const char *filename,
1135 struct government *fallback)
1136{
1137 const char *sval;
1138 struct government *gov;
1139
1140 sval = secfile_lookup_str_default(file, NULL, "%s", entry);
1141 if (!sval) {
1142 gov = fallback;
1143 } else {
1145 }
1146 if (!gov) {
1148 "\"%s\" %s: couldn't match \"%s\".",
1149 filename, entry, sval);
1150 }
1151 return gov;
1152}
1153
1154/**********************************************************************/
1157static char *lookup_string(struct section_file *file, const char *prefix,
1158 const char *suffix)
1159{
1160 const char *sval = secfile_lookup_str(file, "%s.%s", prefix, suffix);
1161
1162 if (NULL != sval) {
1163 char copy[strlen(sval) + 1];
1164
1165 strcpy(copy, sval);
1167 if (strlen(copy) > 0) {
1168 return fc_strdup(copy);
1169 }
1170 }
1171 return NULL;
1172}
1173
1174/**********************************************************************/
1177static struct strvec *lookup_strvec(struct section_file *file,
1178 const char *prefix, const char *suffix)
1179{
1180 size_t dim;
1181 const char **vec = secfile_lookup_str_vec(file, &dim,
1182 "%s.%s", prefix, suffix);
1183
1184 if (NULL != vec) {
1185 struct strvec *dest = strvec_new();
1186
1187 strvec_store(dest, vec, dim);
1188 free(vec);
1189 return dest;
1190 }
1191 return NULL;
1192}
1193
1194/**********************************************************************/
1197static struct extra_type *lookup_resource(const char *filename,
1198 const char *name,
1199 const char *jsection)
1200{
1201 struct extra_type *pres;
1202
1204
1205 if (pres == NULL) {
1207 "\"%s\" [%s] has unknown \"%s\".",
1208 filename, jsection, name);
1209 }
1210
1211 return pres;
1212}
1213
1214/**********************************************************************/
1218static bool lookup_terrain(struct section_file *file,
1219 const char *entry,
1220 const char *filename,
1221 struct terrain *pthis,
1222 struct terrain **result,
1223 bool null_acceptable)
1224{
1225 const int j = terrain_index(pthis);
1226 const char *jsection = &terrain_sections[j * MAX_SECTION_LABEL];
1227 const char *name = secfile_lookup_str(file, "%s.%s", jsection, entry);
1228 struct terrain *pterr;
1229
1230 if (NULL == name && !null_acceptable) {
1231 return FALSE;
1232 }
1233
1234 if (NULL == name
1235 || *name == '\0'
1236 || (0 == strcmp(name, "none"))
1237 || (0 == strcmp(name, "no"))) {
1238 *result = T_NONE;
1239
1240 return TRUE;
1241 }
1242 if (0 == strcmp(name, "yes")) {
1243 *result = pthis;
1244
1245 return TRUE;
1246 }
1247
1249 *result = pterr;
1250
1251 if (pterr == NULL) {
1253 "\"%s\" [%s] has unknown \"%s\".",
1254 secfile_name(file), jsection, name);
1255 return FALSE;
1256 }
1257
1258 return TRUE;
1259}
1260
1261/**********************************************************************/
1268bool lookup_time(const struct section_file *secfile, int *turns,
1269 const char *sec_name, const char *property_name,
1270 const char *filename, const char *item_name,
1271 bool *ok)
1272{
1273 /* Assumes that PACKET_UNIT_INFO.activity_count in packets.def is UINT16 */
1274 const int max_turns = 65535 / ACTIVITY_FACTOR;
1275
1276 if (!secfile_lookup_int(secfile, turns, "%s.%s", sec_name, property_name)) {
1277 return FALSE;
1278 }
1279
1280 if (*turns > max_turns) {
1282 "\"%s\": \"%s\": \"%s\" value %d too large (max %d)",
1283 filename, item_name ? item_name : sec_name,
1284 property_name, *turns, max_turns);
1285 *ok = FALSE;
1286 }
1287
1288 return TRUE; /* we found _something */
1289}
1290
1291/**********************************************************************/
1295 const char *domain,
1296 struct section_file *file,
1297 const char *sec_name)
1298{
1299 const char *name = secfile_lookup_str(file, "%s.name", sec_name);
1300 const char *rule_name = secfile_lookup_str(file, "%s.rule_name", sec_name);
1301
1302 if (!name) {
1304 "\"%s\" [%s]: no \"name\" specified.",
1305 secfile_name(file), sec_name);
1306 return FALSE;
1307 }
1308
1309 names_set(pname, domain, name, rule_name);
1310
1311 return TRUE;
1312}
1313
1314/**********************************************************************/
1318 struct section_file *file,
1319 const char *secname, const char *field_prefix)
1320{
1321 enum trait tr;
1322
1323 /* FIXME: Use specenum trait names without duplicating them here.
1324 * Just needs to take care of case.
1325 * This list is also duplicated in rulesave.c:save_traits() */
1326 const char *trait_names[] = {
1327 "expansionist",
1328 "trader",
1329 "aggressive",
1330 "builder",
1331 NULL
1332 };
1333
1334 for (tr = trait_begin(); tr != trait_end() && trait_names[tr] != NULL; tr = trait_next(tr)) {
1335 out[tr].min = secfile_lookup_int_default(file, -1, "%s.%s%s_min",
1336 secname,
1338 trait_names[tr]);
1339 out[tr].max = secfile_lookup_int_default(file, -1, "%s.%s%s_max",
1340 secname,
1342 trait_names[tr]);
1343 out[tr].fixed = secfile_lookup_int_default(file, -1, "%s.%s%s_default",
1344 secname,
1346 trait_names[tr]);
1347 }
1348
1349 fc_assert(tr == trait_end()); /* number of trait_names correct */
1350}
1351
1352/**********************************************************************/
1356static bool load_game_names(struct section_file *file,
1357 struct rscompat_info *compat)
1358{
1359 struct section_list *sec;
1360 int nval;
1361 const char *filename = secfile_name(file);
1362 bool ok = TRUE;
1363
1364 /* section: datafile */
1366 if (compat->version <= 0) {
1367 return FALSE;
1368 }
1369
1370 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1371 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1372
1374 nval = (NULL != sec ? section_list_size(sec) : 0);
1376 int num = nval; /* No "size_t" to printf */
1377
1379 "\"%s\": Too many achievement types (%d, max %d)",
1380 filename, num, MAX_ACHIEVEMENT_TYPES);
1381 ok = FALSE;
1382 } else {
1384 }
1385
1386 if (ok) {
1389
1390 if (!ruleset_load_names(&pach->name, NULL, file, sec_name)) {
1392 "\"%s\": Cannot load achievement names",
1393 filename);
1394 ok = FALSE;
1395 break;
1396 }
1398 }
1399
1401
1402 if (ok) {
1404
1405 nval = (NULL != sec ? section_list_size(sec) : 0);
1406 if (nval > MAX_GOODS_TYPES) {
1407 int num = nval; /* No "size_t" to printf */
1408
1410 "\"%s\": Too many goods types (%d, max %d)",
1411 filename, num, MAX_GOODS_TYPES);
1413 ok = FALSE;
1414 } else if (nval < 1) {
1416 "\"%s\": At least one goods type needed",
1417 filename);
1419 ok = FALSE;
1420 } else {
1422 }
1423
1424 if (ok) {
1426 const char *sec_name
1428
1429 if (!ruleset_load_names(&pgood->name, NULL, file, sec_name)) {
1431 "\"%s\": Cannot load goods names",
1432 filename);
1433 ok = FALSE;
1434 break;
1435 }
1437 }
1439 }
1440
1441 if (ok) {
1442
1444
1445 nval = (NULL != sec ? section_list_size(sec) : 0);
1446 if (nval > MAX_COUNTERS) {
1447 size_t num = nval;
1448
1450 "\"%s\": Too many counters (" SIZE_T_PRINTF ", max %d)",
1451 filename, num, MAX_COUNTERS);
1452 ok = FALSE;
1453 }
1454
1455 if (ok) {
1456 int count_idx;
1457
1459
1460 for (count_idx = 0; count_idx < nval; count_idx++) {
1461
1463 const char *sec_name
1465
1466 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
1468 "\"%s\": Cannot load counters names",
1469 filename);
1470 ok = FALSE;
1471 break;
1472 }
1473 }
1474 }
1475
1477 }
1478
1479 return ok;
1480}
1481
1482/**********************************************************************/
1486static bool load_action_names(struct section_file *file,
1487 struct rscompat_info *compat)
1488{
1489 const char *filename = secfile_name(file);
1490 bool ok = TRUE;
1491
1492 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1493 return FALSE;
1494 }
1495
1496 (void) secfile_entry_by_path(file, "datafile.description"); /* Unused */
1497 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* Unused */
1498
1499 return ok;
1500}
1501
1502/**********************************************************************/
1506static bool load_tech_names(struct section_file *file,
1507 struct rscompat_info *compat)
1508{
1509 struct section_list *sec = NULL;
1510 /* Number of techs in the ruleset (means without A_NONE). */
1511 int num_techs = 0;
1512 int i;
1513 const char *filename = secfile_name(file);
1514 bool ok = TRUE;
1515 const char *flag;
1516
1517 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1518 return FALSE;
1519 }
1520
1521 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1522 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1523
1524 /* User tech flag names */
1525 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1526 i++) {
1527 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1528 i);
1531 "\"%s\": Duplicate tech flag name '%s'",
1532 filename, flag);
1533 ok = FALSE;
1534 break;
1535 }
1536 if (i > MAX_NUM_USER_TECH_FLAGS) {
1538 "\"%s\": Too many user tech flags!",
1539 filename);
1540 ok = FALSE;
1541 break;
1542 }
1543
1544 set_user_tech_flag_name(TECH_USER_1 + i, flag, helptxt);
1545 }
1546
1547 if (ok) {
1548 size_t nval;
1549
1550 for (; i < MAX_NUM_USER_TECH_FLAGS; i++) {
1552 }
1553
1554 /* Tech classes */
1556
1557 nval = (NULL != sec ? section_list_size(sec) : 0);
1558 if (nval > MAX_NUM_TECH_CLASSES) {
1559 int num = nval; /* No "size_t" to printf */
1560
1562 "\"%s\": Too many tech classes (%d, max %d)",
1563 filename, num, MAX_NUM_TECH_CLASSES);
1565 ok = FALSE;
1566 } else {
1568 }
1569
1570 if (ok) {
1572 const char *sec_name
1574
1575 if (!ruleset_load_names(&ptclass->name, NULL, file, sec_name)) {
1576 ruleset_error(NULL, LOG_ERROR, "\"%s\": Cannot load tech class names",
1577 filename);
1578 ok = FALSE;
1579 break;
1580 }
1582 }
1583 }
1584
1585 if (ok) {
1586 /* The techs: */
1588 if (NULL == sec || 0 == (num_techs = section_list_size(sec))) {
1590 "\"%s\": No Advances?!?", filename);
1591 ok = FALSE;
1592 } else {
1593 log_verbose("%d advances (including possibly unused)", num_techs);
1594 if (num_techs + A_FIRST > A_LAST) {
1596 "\"%s\": Too many advances (%d, max %d)",
1597 filename, num_techs, A_LAST - A_FIRST);
1598 ok = FALSE;
1599 }
1600 }
1601 }
1602
1603 if (ok) {
1604 game.control.num_tech_types = num_techs + A_FIRST; /* includes A_NONE */
1605
1606 i = 0;
1607 advance_iterate(adv) {
1608 if (!ruleset_load_names(&adv->name, NULL, file,
1610 ok = FALSE;
1611 break;
1612 }
1613 i++;
1615 }
1617
1618 return ok;
1619}
1620
1621/**********************************************************************/
1624static bool load_ruleset_techs(struct section_file *file,
1625 struct rscompat_info *compat)
1626{
1627 struct section_list *sec;
1628 const char **slist;
1629 int i;
1630 size_t nval;
1632 const char *filename = secfile_name(file);
1633 bool ok = TRUE;
1634
1636
1637 i = 0;
1639 const char *sec_name = section_name(section_list_get(sec, i));
1640
1641 ptclass->cost_pct = secfile_lookup_int_default(file, 100, "%s.%s",
1642 sec_name, "cost_pct");
1643
1644 i++;
1646
1648
1649 i = 0;
1650 advance_iterate(a) {
1651 const char *sec_name = section_name(section_list_get(sec, i));
1652 const char *sval;
1653 int j, ival;
1654 struct requirement_vector *research_reqs;
1655
1656 if (!lookup_tech(file, &a->require[AR_ONE], sec_name, "req1",
1657 filename, rule_name_get(&a->name))
1658 || !lookup_tech(file, &a->require[AR_TWO], sec_name, "req2",
1659 filename, rule_name_get(&a->name))
1660 || !lookup_tech(file, &a->require[AR_ROOT], sec_name, "root_req",
1661 filename, rule_name_get(&a->name))) {
1662 ok = FALSE;
1663 break;
1664 }
1665
1666 if ((A_NEVER == a->require[AR_ONE] && A_NEVER != a->require[AR_TWO])
1667 || (A_NEVER != a->require[AR_ONE] && A_NEVER == a->require[AR_TWO])) {
1669 "\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
1670 filename, sec_name, rule_name_get(&a->name));
1671 ok = FALSE;
1672 break;
1673 }
1674 if (a_none == a->require[AR_ONE] && a_none != a->require[AR_TWO]) {
1676 "\"%s\" [%s] \"%s\": should have \"None\" second.",
1677 filename, sec_name, rule_name_get(&a->name));
1678 ok = FALSE;
1679 break;
1680 }
1681
1682 if (game.control.num_tech_classes == 0) {
1683 a->tclass = NULL;
1684 } else {
1685 const char *classname;
1686
1687 classname = lookup_string(file, sec_name, "class");
1688 if (classname != NULL) {
1691 if (a->tclass == NULL) {
1693 "\"%s\" [%s] \"%s\": Unknown tech class \"%s\".",
1694 filename, sec_name, rule_name_get(&a->name), classname);
1695 ok = FALSE;
1696 break;
1697 }
1698 } else {
1699 a->tclass = NULL; /* Default */
1700 }
1701 }
1702
1703 research_reqs = lookup_req_list(file, compat, sec_name, "research_reqs",
1704 rule_name_get(&a->name));
1705 if (research_reqs == NULL) {
1706 ok = FALSE;
1707 break;
1708 }
1709
1710 requirement_vector_copy(&a->research_reqs, research_reqs);
1711
1712 BV_CLR_ALL(a->flags);
1713
1714 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
1715 for (j = 0; j < nval; j++) {
1716 sval = slist[j];
1717 if (strcmp(sval, "") == 0) {
1718 continue;
1719 }
1723 "\"%s\" [%s] \"%s\": bad flag name \"%s\".",
1724 filename, sec_name, rule_name_get(&a->name), sval);
1725 ok = FALSE;
1726 break;
1727 } else {
1728 BV_SET(a->flags, ival);
1729 }
1730 }
1731 free(slist);
1732
1733 if (!ok) {
1734 break;
1735 }
1736
1737 sz_strlcpy(a->graphic_str,
1738 secfile_lookup_str_default(file, "-", "%s.graphic", sec_name));
1739 sz_strlcpy(a->graphic_alt,
1741 "%s.graphic_alt", sec_name));
1742
1743 a->helptext = lookup_strvec(file, sec_name, "helptext");
1744 a->bonus_message = lookup_string(file, sec_name, "bonus_message");
1745 a->cost = secfile_lookup_int_default(file, -1, "%s.%s",
1746 sec_name, "cost");
1747 a->num_reqs = 0;
1748
1749 i++;
1751
1752 /* Propagate a root tech up into the tech tree. If a technology
1753 * X has Y has a root tech, then any technology requiring X (in the
1754 * normal way or as a root tech) also has Y as a root tech.
1755 * Later techs may gain a whole set of root techs in this way. The one
1756 * we store in AR_ROOT is a more or less arbitrary one of these,
1757 * also signalling that the set is non-empty; after this, you'll still
1758 * have to walk the tech tree to find them all. */
1759restart:
1760
1761 if (ok) {
1762 advance_iterate(a) {
1763 if (valid_advance(a)
1764 && A_NEVER != a->require[AR_ROOT]) {
1765 bool out_of_order = FALSE;
1766
1767 /* Now find any tech depending on this technology and update its
1768 * root_req. */
1769 advance_iterate(b) {
1770 if (valid_advance(b)
1771 && A_NEVER == b->require[AR_ROOT]
1772 && (a == b->require[AR_ONE] || a == b->require[AR_TWO])) {
1773 b->require[AR_ROOT] = a->require[AR_ROOT];
1774 b->inherited_root_req = TRUE;
1775 if (b < a) {
1777 }
1778 }
1780
1781 if (out_of_order) {
1782 /* HACK: If we just changed the root_tech of a lower-numbered
1783 * technology, we need to go back so that we can propagate the
1784 * root_tech up to that technology's parents... */
1785 goto restart;
1786 }
1787 }
1789
1790 /* Now rename A_NEVER to A_NONE for consistency */
1792 if (A_NEVER == a->require[AR_ROOT]) {
1793 a->require[AR_ROOT] = a_none;
1794 }
1796
1797 /* Some more consistency checking:
1798 Non-removed techs depending on removed techs is too
1799 broken to fix by default, so die.
1800 */
1801 advance_iterate(a) {
1802 if (valid_advance(a)) {
1803 /* We check for recursive tech loops later,
1804 * in build_required_techs_helper. */
1805 if (!valid_advance(a->require[AR_ONE])) {
1807 "\"%s\" tech \"%s\": req1 leads to removed tech.",
1808 filename, advance_rule_name(a));
1809 ok = FALSE;
1810 break;
1811 }
1812 if (!valid_advance(a->require[AR_TWO])) {
1814 "\"%s\" tech \"%s\": req2 leads to removed tech.",
1815 filename, advance_rule_name(a));
1816 ok = FALSE;
1817 break;
1818 }
1819 }
1821 }
1822
1824 if (ok) {
1826 }
1827
1828 return ok;
1829}
1830
1831/**********************************************************************/
1835static bool load_unit_names(struct section_file *file,
1836 struct rscompat_info *compat)
1837{
1838 struct section_list *sec = NULL;
1839 int nval = 0;
1840 int i;
1841 const char *filename = secfile_name(file);
1842 const char *flag;
1843 bool ok = TRUE;
1844
1845 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1846 return FALSE;
1847 }
1848
1849 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1850 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1851
1852 /* User unit flag names */
1853 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1854 i++) {
1855 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1856 i);
1857
1861 "\"%s\": Duplicate unit flag name '%s'",
1862 filename, flag);
1863 ok = FALSE;
1864 break;
1865 }
1866 if (i > MAX_NUM_USER_UNIT_FLAGS) {
1868 "\"%s\": Too many user unit type flags!",
1869 filename);
1870 ok = FALSE;
1871 break;
1872 }
1873
1875 }
1876
1877 if (ok) {
1878 /* Blank the remaining unit type user flags. */
1879 for (; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
1881 }
1882 }
1883
1884 if (ok) {
1885 /* User unit class flag names */
1886 for (i = 0;
1887 (flag = secfile_lookup_str_default(file, NULL,
1888 "control.class_flags%d.name",
1889 i));
1890 i++) {
1891 const char *helptxt = secfile_lookup_str_default(file, NULL,
1892 "control.class_flags%d.helptxt", i);
1893
1897 "\"%s\": Duplicate unit class flag name '%s'",
1898 filename, flag);
1899 ok = FALSE;
1900 break;
1901 }
1904 "\"%s\": Too many user unit class flags!",
1905 filename);
1906 ok = FALSE;
1907 break;
1908 }
1909
1911 }
1912 }
1913
1914 if (ok) {
1915 /* Blank the remaining unit class user flags. */
1916 for (; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
1918 }
1919 }
1920
1921 if (ok) {
1922 /* Unit classes */
1924 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1926 "\"%s\": No unit classes?!?", filename);
1927 ok = FALSE;
1928 } else {
1929 log_verbose("%d unit classes", nval);
1930 if (nval > UCL_LAST) {
1932 "\"%s\": Too many unit classes (%d, max %d)",
1933 filename, nval, UCL_LAST);
1934 ok = FALSE;
1935 }
1936 }
1937 }
1938
1939 if (ok) {
1941
1943 const int pci = uclass_index(punitclass);
1944
1945 if (!ruleset_load_names(&punitclass->name, NULL, file,
1947 ok = FALSE;
1948 break;
1949 }
1951 }
1953 sec = NULL;
1954
1955 /* The names: */
1956 if (ok) {
1958 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1960 "\"%s\": No unit types?!?", filename);
1961 ok = FALSE;
1962 } else {
1963 log_verbose("%d unit types (including possibly unused)", nval);
1964 if (nval > U_LAST) {
1966 "\"%s\": Too many unit types (%d, max %d)",
1967 filename, nval, U_LAST);
1968 ok = FALSE;
1969 }
1970 }
1971 }
1972
1973 if (ok) {
1975
1977 const int utypei = utype_index(punittype);
1978 if (!ruleset_load_names(&punittype->name, NULL, file,
1980 ok = FALSE;
1981 break;
1982 }
1984 }
1986
1987 return ok;
1988}
1989
1990/**********************************************************************/
1993static bool load_ruleset_veteran(struct section_file *file,
1994 const char *path,
1995 struct veteran_system **vsystem, char *err,
1996 size_t err_len)
1997{
1998 const char **vlist_name;
2001 int i;
2002 bool ret = TRUE;
2003
2004 /* The pointer should be uninitialised. */
2005 if (*vsystem != NULL) {
2006 fc_snprintf(err, err_len, "Veteran system is defined?!");
2007 return FALSE;
2008 }
2009
2010 /* Load data. */
2012 "%s.veteran_names", path);
2014 "%s.veteran_power_fact", path);
2016 "%s.veteran_base_raise_chance", path);
2018 "%s.veteran_work_raise_chance",
2019 path);
2021 "%s.veteran_move_bonus", path);
2022
2023 if (count_name > MAX_VET_LEVELS) {
2024 ret = FALSE;
2025 fc_snprintf(err, err_len, "\"%s\": Too many veteran levels (section "
2026 "'%s': %lu, max %d)", secfile_name(file), path,
2027 (long unsigned)count_name, MAX_VET_LEVELS);
2028 } else if (count_name != count_power
2031 || count_name != count_move) {
2032 ret = FALSE;
2033 fc_snprintf(err, err_len, "\"%s\": Different lengths for the veteran "
2034 "settings in section '%s'", secfile_name(file),
2035 path);
2036 } else if (count_name == 0) {
2037 /* Nothing defined. */
2038 *vsystem = NULL;
2039 } else {
2040 /* Generate the veteran system. */
2042
2043#define rs_sanity_veteran(_path, _entry, _i, _condition, _action) \
2044 if (_condition) { \
2045 log_error("Invalid veteran definition '%s.%s[%d]'!", \
2046 _path, _entry, _i); \
2047 log_debug("Failed check: '%s'. Update value: '%s'.", \
2048 #_condition, #_action); \
2049 _action; \
2050 }
2051 for (i = 0; i < count_name; i++) {
2052 /* Some sanity checks. */
2053 rs_sanity_veteran(path, "veteran_power_fact", i,
2054 (vlist_power[i] < 0), vlist_power[i] = 0);
2055 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2056 (vlist_raise[i] < 0), vlist_raise[i] = 0);
2057 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2058 (vlist_wraise[i] < 0), vlist_wraise[i] = 0);
2059 rs_sanity_veteran(path, "veteran_move_bonus", i,
2060 (vlist_move[i] < 0), vlist_move[i] = 0);
2061 if (i == 0) {
2062 /* First element.*/
2063 rs_sanity_veteran(path, "veteran_power_fact", i,
2064 (vlist_power[i] != 100), vlist_power[i] = 100);
2065 } else if (i == count_name - 1) {
2066 /* Last element. */
2067 rs_sanity_veteran(path, "veteran_power_fact", i,
2068 (vlist_power[i] < vlist_power[i - 1]),
2069 vlist_power[i] = vlist_power[i - 1]);
2070 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2071 (vlist_raise[i] != 0), vlist_raise[i] = 0);
2072 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2073 (vlist_wraise[i] != 0), vlist_wraise[i] = 0);
2074 } else {
2075 /* All elements in between. */
2076 rs_sanity_veteran(path, "veteran_power_fact", i,
2077 (vlist_power[i] < vlist_power[i - 1]),
2078 vlist_power[i] = vlist_power[i - 1]);
2079 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2080 (vlist_raise[i] > 100), vlist_raise[i] = 100);
2081 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2082 (vlist_wraise[i] > 100), vlist_wraise[i] = 100);
2083 }
2084
2087 vlist_wraise[i]);
2088 }
2089#undef rs_sanity_veteran
2090 }
2091
2092 if (vlist_name) {
2094 }
2095 if (vlist_power) {
2097 }
2098 if (vlist_raise) {
2100 }
2101 if (vlist_wraise) {
2103 }
2104 if (vlist_move) {
2106 }
2107
2108 return ret;
2109}
2110
2111/**********************************************************************/
2114static bool load_ruleset_units(struct section_file *file,
2115 struct rscompat_info *compat)
2116{
2117 int j, ival;
2118 size_t nval;
2119 struct section_list *sec, *csec;
2120 const char *sval, **slist;
2121 const char *filename = secfile_name(file);
2122 char msg[MAX_LEN_MSG];
2123 bool ok = TRUE;
2124
2125 if (!load_ruleset_veteran(file, "veteran_system", &game.veteran, msg,
2126 sizeof(msg))
2127 || game.veteran == NULL) {
2129 "Error loading the default veteran system: %s",
2130 msg);
2131 ok = FALSE;
2132 }
2133
2135 nval = (NULL != sec ? section_list_size(sec) : 0);
2136
2138 nval = (NULL != csec ? section_list_size(csec) : 0);
2139
2140 if (ok) {
2142 int i = uclass_index(uc);
2143 const char *sec_name = section_name(section_list_get(csec, i));
2144
2145 if (secfile_lookup_int(file, &uc->min_speed, "%s.min_speed", sec_name)) {
2146 uc->min_speed *= SINGLE_MOVE;
2147 } else {
2149 ok = FALSE;
2150 break;
2151 }
2152 if (!secfile_lookup_int(file, &uc->hp_loss_pct,
2153 "%s.hp_loss_pct", sec_name)) {
2155 ok = FALSE;
2156 break;
2157 }
2158
2159 uc->non_native_def_pct = secfile_lookup_int_default(file, 100,
2160 "%s.non_native_def_pct",
2161 sec_name);
2162
2163 BV_CLR_ALL(uc->flags);
2164 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
2165 for (j = 0; j < nval; j++) {
2166 sval = slist[j];
2167 if (strcmp(sval, "") == 0) {
2168 continue;
2169 }
2172 ok = FALSE;
2176 "\"%s\" unit_class \"%s\": unit_type flag \"%s\"!",
2177 filename, uclass_rule_name(uc), sval);
2178 } else {
2180 "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
2181 filename, uclass_rule_name(uc), sval);
2182 }
2183 break;
2184 } else {
2185 BV_SET(uc->flags, ival);
2186 }
2187 }
2188 free(slist);
2189
2190 uc->helptext = lookup_strvec(file, sec_name, "helptext");
2191
2192 if (!ok) {
2193 break;
2194 }
2196 }
2197
2198 if (ok) {
2199 /* Tech and Gov requirements; per unit veteran system */
2201 const int i = utype_index(u);
2202 const struct section *psection = section_list_get(sec, i);
2203 const char *sec_name = section_name(psection);
2204
2205 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
2206 struct advance *adv_req;
2207 struct impr_type *impr_req = NULL;
2208
2209 if (!lookup_tech(file, &adv_req, sec_name,
2210 "tech_req", filename,
2211 rule_name_get(&u->name))) {
2212 ok = FALSE;
2213 break;
2214 }
2215 if (adv_req == A_NEVER) {
2216 ruleset_error(NULL, LOG_ERROR, "%s lacks valid tech_req.",
2217 rule_name_get(&u->name));
2218 ok = FALSE;
2219 break;
2220 } else if (adv_req != advance_by_number(A_NONE)) {
2221 requirement_vector_append(&u->build_reqs,
2223 FALSE, TRUE, FALSE,
2225 }
2226
2227 /* Read the government build requirement from the old ruleset format
2228 * and put it in unit_type's build_reqs requirement vector.
2229 * The build_reqs requirement vector isn't ready to be exposed in the
2230 * ruleset yet.
2231 * Barbarians can build certain units as long as anyone in the world
2232 * has the required tech. Regular players must have the required tech
2233 * them self to build the same unit. One way to solve this is to make
2234 * unit building an action enabler controlled action with a city (not
2235 * unit) actor.
2236 * Putting a requirement vector on unit types in the ruleset will
2237 * force ruleset authors to change all their unit type build
2238 * requirements to a requirement vector. Forcing them to convert their
2239 * unit type requirements again in the next version (should building be
2240 * switched to an action enabler with a city actor) is not good. */
2241 if (NULL != section_entry_by_name(psection, "gov_req")) {
2242 char tmp[200] = "\0";
2244
2245 fc_strlcat(tmp, section_name(psection), sizeof(tmp));
2246 fc_strlcat(tmp, ".gov_req", sizeof(tmp));
2247 need_government = lookup_government(file, tmp, filename, NULL);
2248 if (need_government == NULL) {
2249 ok = FALSE;
2250 break;
2251 }
2254 FALSE, TRUE, FALSE,
2256 }
2257
2258 /* Read the building build requirement from the old ruleset format
2259 * and put it in unit_type's build_reqs requirement vector.
2260 * The build_reqs requirement vector isn't ready to be exposed in the
2261 * ruleset yet.
2262 * See the comment for gov_req above for why. */
2263 if (!lookup_building(file, sec_name, "impr_req",
2264 &impr_req, filename,
2265 rule_name_get(&u->name))) {
2266 ok = FALSE;
2267 break;
2268 }
2269 if (impr_req) {
2272 FALSE, TRUE, FALSE,
2274 }
2275 } else {
2276 /* Freeciv-3.2 format */
2277 struct requirement_vector *reqs;
2278
2279 reqs = lookup_req_list(file, compat, sec_name, "reqs",
2280 utype_rule_name(u));
2281
2282 if (reqs == NULL) {
2283 ok = FALSE;
2284 break;
2285 }
2286
2287 requirement_vector_copy(&u->build_reqs, reqs);
2288 }
2289
2290 if (!load_ruleset_veteran(file, sec_name, &u->veteran,
2291 msg, sizeof(msg))) {
2293 "Error loading the veteran system: %s",
2294 msg);
2295 ok = FALSE;
2296 break;
2297 }
2298
2299 if (!lookup_unit_type(file, sec_name, "obsolete_by",
2300 &u->obsoleted_by, filename,
2301 rule_name_get(&u->name))
2302 || !lookup_unit_type(file, sec_name, "convert_to",
2303 &u->converted_to, filename,
2304 rule_name_get(&u->name))) {
2305 ok = FALSE;
2306 break;
2307 }
2308 u->convert_time = 1; /* default */
2309 lookup_time(file, &u->convert_time, sec_name, "convert_time",
2310 filename, rule_name_get(&u->name), &ok);
2312 }
2313
2314 if (ok) {
2315 /* main stats: */
2317 const int i = utype_index(u);
2318 struct unit_class *pclass;
2319 const char *sec_name = section_name(section_list_get(sec, i));
2320 const char *str;
2321
2322 sval = secfile_lookup_str(file, "%s.class", sec_name);
2324 if (!pclass) {
2326 "\"%s\" unit_type \"%s\": bad class \"%s\".",
2327 filename, utype_rule_name(u), sval);
2328 ok = FALSE;
2329 break;
2330 }
2331 u->uclass = pclass;
2332
2333 sz_strlcpy(u->sound_move,
2334 secfile_lookup_str_default(file, "-", "%s.sound_move",
2335 sec_name));
2336 sz_strlcpy(u->sound_move_alt,
2337 secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
2338 sec_name));
2339 sz_strlcpy(u->sound_fight,
2340 secfile_lookup_str_default(file, "-", "%s.sound_fight",
2341 sec_name));
2342 sz_strlcpy(u->sound_fight_alt,
2343 secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
2344 sec_name));
2345
2346 if ((str = secfile_lookup_str(file, "%s.graphic", sec_name))) {
2347 sz_strlcpy(u->graphic_str, str);
2348 } else {
2350 ok = FALSE;
2351 break;
2352 }
2353 sz_strlcpy(u->graphic_alt,
2354 secfile_lookup_str_default(file, "-", "%s.graphic_alt",
2355 sec_name));
2356 sz_strlcpy(u->graphic_alt2,
2357 secfile_lookup_str_default(file, "-", "%s.graphic_alt2",
2358 sec_name));
2359
2360 if (!secfile_lookup_int(file, &u->build_cost,
2361 "%s.build_cost", sec_name)
2362 || !secfile_lookup_int(file, &u->pop_cost,
2363 "%s.pop_cost", sec_name)
2364 || !secfile_lookup_int(file, &u->attack_strength,
2365 "%s.attack", sec_name)
2366 || !secfile_lookup_int(file, &u->defense_strength,
2367 "%s.defense", sec_name)
2368 || !secfile_lookup_int(file, &u->move_rate,
2369 "%s.move_rate", sec_name)
2370 || !secfile_lookup_int(file, &u->vision_radius_sq,
2371 "%s.vision_radius_sq", sec_name)
2372 || !secfile_lookup_int(file, &u->transport_capacity,
2373 "%s.transport_cap", sec_name)
2374 || !secfile_lookup_int(file, &u->firepower,
2375 "%s.firepower", sec_name)
2376 || !secfile_lookup_int(file, &u->fuel,
2377 "%s.fuel", sec_name)
2378 || !secfile_lookup_int(file, &u->happy_cost,
2379 "%s.uk_happy", sec_name)) {
2381 ok = FALSE;
2382 break;
2383 }
2384 u->hp
2387 RS_MIN_HP,
2388 RS_MAX_HP,
2389 "%s.hitpoints", sec_name);
2390
2391 u->move_rate *= SINGLE_MOVE;
2392
2393 if (u->firepower <= 0) {
2395 "\"%s\" unit_type \"%s\":"
2396 " firepower is %d,"
2397 " but must be at least 1. "
2398 " If you want no attack ability,"
2399 " set the unit's attack strength to 0.",
2400 filename, utype_rule_name(u), u->firepower);
2401 ok = FALSE;
2402 break;
2403 }
2404
2405 lookup_cbonus_list(u->bonuses, file, sec_name, "bonuses");
2406
2408 u->upkeep[o] = secfile_lookup_int_default(file, 0, "%s.uk_%s",
2409 sec_name,
2412
2413 slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec_name);
2414
2415 BV_CLR_ALL(u->cargo);
2416 for (j = 0; j < nval; j++) {
2417 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2418
2419 if (!uclass) {
2421 "\"%s\" unit_type \"%s\":"
2422 "has unknown unit class %s as cargo.",
2423 filename, utype_rule_name(u), slist[j]);
2424 ok = FALSE;
2425 break;
2426 }
2427
2428 BV_SET(u->cargo, uclass_index(uclass));
2429 }
2430 free(slist);
2431
2432 if (!ok) {
2433 break;
2434 }
2435
2436 slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec_name);
2437 BV_CLR_ALL(u->targets);
2438 for (j = 0; j < nval; j++) {
2439 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2440
2441 if (!uclass) {
2443 "\"%s\" unit_type \"%s\":"
2444 "has unknown unit class %s as target.",
2445 filename, utype_rule_name(u), slist[j]);
2446 ok = FALSE;
2447 break;
2448 }
2449
2450 BV_SET(u->targets, uclass_index(uclass));
2451 }
2452 free(slist);
2453
2454 if (!ok) {
2455 break;
2456 }
2457
2458 slist = secfile_lookup_str_vec(file, &nval, "%s.embarks", sec_name);
2459 BV_CLR_ALL(u->embarks);
2460 for (j = 0; j < nval; j++) {
2461 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2462
2463 if (!uclass) {
2465 "\"%s\" unit_type \"%s\":"
2466 "has unknown unit class %s as embarkable.",
2467 filename, utype_rule_name(u), slist[j]);
2468 ok = FALSE;
2469 break;
2470 }
2471
2472 BV_SET(u->embarks, uclass_index(uclass));
2473 }
2474 free(slist);
2475
2476 if (!ok) {
2477 break;
2478 }
2479
2480 slist = secfile_lookup_str_vec(file, &nval, "%s.disembarks", sec_name);
2481 BV_CLR_ALL(u->disembarks);
2482 for (j = 0; j < nval; j++) {
2483 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2484
2485 if (!uclass) {
2487 "\"%s\" unit_type \"%s\":"
2488 "has unknown unit class %s as disembarkable.",
2489 filename, utype_rule_name(u), slist[j]);
2490 ok = FALSE;
2491 break;
2492 }
2493
2494 BV_SET(u->disembarks, uclass_index(uclass));
2495 }
2496 free(slist);
2497
2498 if (!ok) {
2499 break;
2500 }
2501
2502 /* Set also all classes that are never unreachable as targets,
2503 * embarks, and disembarks. */
2506 BV_SET(u->targets, uclass_index(preachable));
2507 BV_SET(u->embarks, uclass_index(preachable));
2508 BV_SET(u->disembarks, uclass_index(preachable));
2509 }
2511
2512 str = secfile_lookup_str_default(file, "Main", "%s.vision_layer",
2513 sec_name);
2515 if (!vision_layer_is_valid(u->vlayer)) {
2517 "\"%s\" unit_type \"%s\":"
2518 "has unknown vision layer %s.",
2519 filename, utype_rule_name(u), str);
2520 ok = FALSE;
2521 break;
2522 }
2523
2524 u->helptext = lookup_strvec(file, sec_name, "helptext");
2525
2526 u->paratroopers_range = secfile_lookup_int_default(file,
2527 0, "%s.paratroopers_range", sec_name);
2528
2529 u->bombard_rate = secfile_lookup_int_default(file, 0,
2530 "%s.bombard_rate", sec_name);
2531 u->city_slots = secfile_lookup_int_default(file, 0,
2532 "%s.city_slots", sec_name);
2533 u->city_size = secfile_lookup_int_default(file, 1,
2534 "%s.city_size", sec_name);
2535
2537 "%s.tp_defense", sec_name);
2538 u->tp_defense = transp_def_type_by_name(sval, fc_strcasecmp);
2539 if (!transp_def_type_is_valid(u->tp_defense)) {
2541 "\"%s\" unit_type \"%s\":"
2542 " bad tp_defense \"%s\".",
2543 filename, utype_rule_name(u), sval);
2544 ok = FALSE;
2545 break;
2546 }
2548 }
2549
2550 if (ok) {
2551 /* flags */
2553 const int i = utype_index(u);
2554
2555 BV_CLR_ALL(u->flags);
2557
2558 slist = secfile_lookup_str_vec(file, &nval, "%s.flags",
2560 for (j = 0; j < nval; j++) {
2561 sval = slist[j];
2562 if (0 == strcmp(sval, "")) {
2563 continue;
2564 }
2567 ok = FALSE;
2571 "\"%s\" unit_type \"%s\": unit_class flag!",
2572 filename, utype_rule_name(u));
2573 } else {
2575 "\"%s\" unit_type \"%s\": bad flag name \"%s\".",
2576 filename, utype_rule_name(u), sval);
2577 }
2578 break;
2579 } else {
2580 BV_SET(u->flags, ival);
2581 }
2582 }
2583 free(slist);
2584
2585 if (!ok) {
2586 break;
2587 }
2589 }
2590
2591 /* roles */
2592 if (ok) {
2594 const int i = utype_index(u);
2595
2596 BV_CLR_ALL(u->roles);
2597
2598 slist = secfile_lookup_str_vec(file, &nval, "%s.roles",
2600 for (j = 0; j < nval; j++) {
2601 sval = slist[j];
2602 if (strcmp(sval, "") == 0) {
2603 continue;
2604 }
2608 "\"%s\" unit_type \"%s\": bad role name \"%s\".",
2609 filename, utype_rule_name(u), sval);
2610 ok = FALSE;
2611 break;
2612 } else {
2613 BV_SET(u->roles, ival - L_FIRST);
2614 }
2616 }
2617 free(slist);
2619 }
2620
2621 if (ok) {
2622 /* Some more consistency checking: */
2625 if (!valid_advance(padv)) {
2627 "\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
2628 filename, utype_rule_name(u),
2630 ok = FALSE;
2631 break;
2632 }
2634
2635 if (!ok) {
2636 break;
2637 }
2639 }
2640
2643
2644 if (ok) {
2646 }
2647
2648 return ok;
2649}
2650
2651/**********************************************************************/
2655static bool load_building_names(struct section_file *file,
2656 struct rscompat_info *compat)
2657{
2658 struct section_list *sec;
2659 int i, nval = 0;
2660 const char *filename = secfile_name(file);
2661 bool ok = TRUE;
2662 const char *flag;
2663
2664 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2665 return FALSE;
2666 }
2667
2668 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2669 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2670
2671 /* The names: */
2673 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2675 "\"%s\": No improvements?!?", filename);
2676 ok = FALSE;
2677 } else {
2678 log_verbose("%d improvement types (including possibly unused)", nval);
2679 if (nval > B_LAST) {
2681 "\"%s\": Too many improvements (%d, max %d)",
2682 filename, nval, B_LAST);
2683 ok = FALSE;
2684 }
2685 }
2686
2687 if (ok) {
2689
2690 for (i = 0; i < nval; i++) {
2691 struct impr_type *b = improvement_by_number(i);
2692
2693 if (!ruleset_load_names(&b->name, NULL, file, section_name(section_list_get(sec, i)))) {
2694 ok = FALSE;
2695 break;
2696 }
2697 }
2698 }
2699
2700 /* User building flag names */
2701 for (i = 0;
2702 (flag = secfile_lookup_str_default(file, NULL,
2703 "control.building_flags%d.name",
2704 i));
2705 i++) {
2706 const char *helptxt = secfile_lookup_str_default(file, NULL,
2707 "control.building_flags%d.helptxt", i);
2708
2710 != impr_flag_id_invalid()) {
2712 "\"%s\": Duplicate building flag name '%s'",
2713 filename, flag);
2714 ok = FALSE;
2715 break;
2716 }
2719 "\"%s\": Too many user building flags!",
2720 filename);
2721 ok = FALSE;
2722 break;
2723 }
2724
2725 set_user_impr_flag_name(IF_USER_FLAG_1 + i, flag, helptxt);
2726 }
2727
2729
2730 return ok;
2731}
2732
2733/**********************************************************************/
2736static bool load_ruleset_buildings(struct section_file *file,
2737 struct rscompat_info *compat)
2738{
2739 struct section_list *sec;
2740 const char *item;
2741 int i, nval;
2742 const char *filename = secfile_name(file);
2743 bool ok = TRUE;
2744
2746 nval = (NULL != sec ? section_list_size(sec) : 0);
2747
2748 for (i = 0; i < nval && ok; i++) {
2749 struct impr_type *b = improvement_by_number(i);
2750 const char *sec_name = section_name(section_list_get(sec, i));
2751 struct requirement_vector *reqs =
2752 lookup_req_list(file, compat, sec_name, "reqs",
2754
2755 if (reqs == NULL) {
2756 ok = FALSE;
2757 break;
2758 } else {
2759 const char *sval, **slist;
2760 int j, ival;
2761 size_t nflags;
2762
2763 item = secfile_lookup_str(file, "%s.genus", sec_name);
2765 if (!impr_genus_id_is_valid(b->genus)) {
2767 "\"%s\" improvement \"%s\": couldn't match "
2768 "genus \"%s\".", filename,
2770 ok = FALSE;
2771 break;
2772 }
2773
2774 slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec_name);
2775 BV_CLR_ALL(b->flags);
2776
2777 for (j = 0; j < nflags; j++) {
2778 sval = slist[j];
2779 if (strcmp(sval, "") == 0) {
2780 continue;
2781 }
2785 "\"%s\" improvement \"%s\": bad flag name \"%s\".",
2786 filename, improvement_rule_name(b), sval);
2787 ok = FALSE;
2788 break;
2789 } else {
2790 BV_SET(b->flags, ival);
2791 }
2792 }
2793 free(slist);
2794
2795 if (!ok) {
2796 break;
2797 }
2798
2799 if (compat->compat_mode) {
2801 }
2802
2804
2805 {
2806 struct requirement_vector *obs_reqs =
2807 lookup_req_list(file, compat, sec_name, "obsolete_by",
2809
2810 if (obs_reqs == NULL) {
2811 ok = FALSE;
2812 break;
2813 } else {
2814 requirement_vector_copy(&b->obsolete_by, obs_reqs);
2815 }
2816 }
2817
2818 if (!secfile_lookup_int(file, &b->build_cost,
2819 "%s.build_cost", sec_name)
2820 || !secfile_lookup_int(file, &b->upkeep,
2821 "%s.upkeep", sec_name)
2822 || !secfile_lookup_int(file, &b->sabotage,
2823 "%s.sabotage", sec_name)) {
2825 ok = FALSE;
2826 break;
2827 }
2828
2831 "%s.graphic", sec_name));
2834 "%s.graphic_alt", sec_name));
2837 "%s.graphic_alt2", sec_name));
2838
2841 "%s.sound", sec_name));
2844 "%s.sound_alt", sec_name));
2847 "%s.sound_alt2", sec_name));
2848 b->helptext = lookup_strvec(file, sec_name, "helptext");
2849 }
2850 }
2851
2853 if (ok) {
2855 }
2856
2857 return ok;
2858}
2859
2860/**********************************************************************/
2864static bool load_terrain_names(struct section_file *file,
2865 struct rscompat_info *compat)
2866{
2867 int nval = 0;
2868 struct section_list *sec = NULL;
2869 const char *flag;
2870 int i;
2871 const char *filename = secfile_name(file);
2872 bool ok = TRUE;
2873
2874 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2875 return FALSE;
2876 }
2877
2878 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2879 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2880
2881 /* User terrain flag names */
2882 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
2883 i++) {
2884 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
2885 i);
2886
2890 "\"%s\": Duplicate terrain flag name '%s'",
2891 filename, flag);
2892 ok = FALSE;
2893 break;
2894 }
2895 if (i > MAX_NUM_USER_TER_FLAGS) {
2897 "\"%s\": Too many user terrain flags!",
2898 filename);
2899 ok = FALSE;
2900 break;
2901 }
2902
2903 set_user_terrain_flag_name(TER_USER_1 + i, flag, helptxt);
2904 }
2905
2906 if (ok) {
2907 /* Blank the remaining terrain user flag slots. */
2908 for (; i < MAX_NUM_USER_TER_FLAGS; i++) {
2910 }
2911 }
2912
2913 /* User extra flag names */
2914 for (i = 0;
2915 (flag = secfile_lookup_str_default(file, NULL,
2916 "control.extra_flags%d.name",
2917 i));
2918 i++) {
2919 const char *helptxt = secfile_lookup_str_default(file, NULL,
2920 "control.extra_flags%d.helptxt", i);
2921
2923 != extra_flag_id_invalid()) {
2925 "\"%s\": Duplicate extra flag name '%s'",
2926 filename, flag);
2927 ok = FALSE;
2928 break;
2929 }
2932 "\"%s\": Too many user extra flags!",
2933 filename);
2934 ok = FALSE;
2935 break;
2936 }
2937
2938 set_user_extra_flag_name(EF_USER_FLAG_1 + i, flag, helptxt);
2939 }
2940
2941 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
2943 }
2944
2945 if (ok) {
2946 /* Blank the remaining extra user flag slots. */
2947 for (; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
2949 }
2950
2951 /* terrain names */
2952
2954 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2956 "\"%s\": ruleset doesn't have any terrains.",
2957 filename);
2958 ok = FALSE;
2959 } else {
2960 if (nval > MAX_NUM_TERRAINS) {
2962 "\"%s\": Too many terrains (%d, max %d)",
2963 filename, nval, MAX_NUM_TERRAINS);
2964 ok = FALSE;
2965 }
2966 }
2967 }
2968
2969 if (ok) {
2971
2972 /* avoid re-reading files */
2973 if (terrain_sections) {
2975 }
2977
2978 terrain_type_iterate(pterrain) {
2979 const int terri = terrain_index(pterrain);
2980 const char *sec_name = section_name(section_list_get(sec, terri));
2981
2982 if (!ruleset_load_names(&pterrain->name, NULL, file, sec_name)) {
2983 ok = FALSE;
2984 break;
2985 }
2986
2989 }
2990
2992 sec = NULL;
2993
2994 /* extra names */
2995
2996 if (ok) {
2998 nval = (NULL != sec ? section_list_size(sec) : 0);
2999 if (nval > MAX_EXTRA_TYPES) {
3001 "\"%s\": Too many extra types (%d, max %d)",
3002 filename, nval, MAX_EXTRA_TYPES);
3003 ok = FALSE;
3004 }
3005 }
3006
3007 if (ok) {
3008 int idx;
3009
3011
3012 if (extra_sections) {
3014 }
3016
3017 if (ok) {
3018 for (idx = 0; idx < nval; idx++) {
3019 const char *sec_name = section_name(section_list_get(sec, idx));
3020 struct extra_type *pextra = extra_by_number(idx);
3021
3022 if (!ruleset_load_names(&pextra->name, NULL, file, sec_name)) {
3023 ok = FALSE;
3024 break;
3025 }
3027 }
3028 }
3029 }
3030
3032 sec = NULL;
3033
3034 /* Base names */
3035
3036 if (ok) {
3038 nval = (NULL != sec ? section_list_size(sec) : 0);
3039 if (nval > MAX_EXTRA_TYPES) {
3041 "\"%s\": Too many base types (%d, max %d)",
3042 filename, nval, MAX_EXTRA_TYPES);
3043 ok = FALSE;
3044 }
3045
3047 }
3048
3049 if (ok) {
3050 int idx;
3051
3052 if (base_sections) {
3054 }
3056
3057 /* Cannot use base_type_iterate() before bases are added to
3058 * EC_BASE caused_by list. Have to get them by extra_type_by_rule_name() */
3059 for (idx = 0; idx < nval; idx++) {
3060 const char *sec_name = section_name(section_list_get(sec, idx));
3061 const char *base_name = secfile_lookup_str(file, "%s.extra", sec_name);
3062
3063 if (base_name != NULL) {
3065
3066 if (pextra != NULL) {
3067 base_type_init(pextra, idx);
3069 } else {
3071 "No extra definition matching base definition \"%s\"",
3072 base_name);
3073 ok = FALSE;
3074 }
3075 } else {
3077 "Base section \"%s\" does not associate base with any extra",
3078 sec_name);
3079 ok = FALSE;
3080 }
3081 }
3082 }
3083
3085 sec = NULL;
3086
3087 /* Road names */
3088
3089 if (ok) {
3091 nval = (NULL != sec ? section_list_size(sec) : 0);
3092 if (nval > MAX_EXTRA_TYPES) {
3094 "\"%s\": Too many road types (%d, max %d)",
3095 filename, nval, MAX_EXTRA_TYPES);
3096 ok = FALSE;
3097 }
3098
3100 }
3101
3102 if (ok) {
3103 int idx;
3104
3105 if (road_sections) {
3107 }
3109
3110 /* Cannot use extra_type_by_cause_iterate(EC_ROAD) before roads are added to
3111 * EC_ROAD caused_by list. Have to get them by extra_type_by_rule_name() */
3112 for (idx = 0; idx < nval; idx++) {
3113 const char *sec_name = section_name(section_list_get(sec, idx));
3114 const char *road_name = secfile_lookup_str(file, "%s.extra", sec_name);
3115
3116 if (road_name != NULL) {
3118
3119 if (pextra != NULL) {
3120 road_type_init(pextra, idx);
3122 } else {
3124 "No extra definition matching road definition \"%s\"",
3125 road_name);
3126 ok = FALSE;
3127 }
3128 } else {
3130 "Road section \"%s\" does not associate road with any extra",
3131 sec_name);
3132 ok = FALSE;
3133 }
3134 }
3135 }
3136
3138 sec = NULL;
3139
3140 /* Resource names */
3141 if (ok) {
3143 nval = (NULL != sec ? section_list_size(sec) : 0);
3144 if (nval > MAX_EXTRA_TYPES) {
3146 "\"%s\": Too many resource types (%d, max %d)",
3147 filename, nval, MAX_EXTRA_TYPES);
3148 ok = FALSE;
3149 }
3150
3152 }
3153
3154 if (ok) {
3155 int idx;
3156
3157 if (resource_sections) {
3159 }
3161
3162 /* Cannot use resource_type_iterate() before resource are added to
3163 * EC_RESOURCE caused_by list. Have to get them by extra_type_by_rule_name() */
3164 for (idx = 0; idx < nval; idx++) {
3165 const char *sec_name = section_name(section_list_get(sec, idx));
3166 const char *resource_name;
3167 struct extra_type *pextra = NULL;
3168
3170
3171 if (resource_name != NULL) {
3173
3174 if (pextra != NULL) {
3175 resource_type_init(pextra);
3177 } else {
3179 "No extra definition matching resource definition \"%s\"",
3181 ok = FALSE;
3182 }
3183 } else {
3185 "Resource section %s does not list extra this resource belongs to.",
3186 sec_name);
3187 ok = FALSE;
3188 }
3189 }
3190 }
3191
3193
3194 return ok;
3195}
3196
3197/**********************************************************************/
3200static bool load_ruleset_terrain(struct section_file *file,
3201 struct rscompat_info *compat)
3202{
3203 size_t nval, nval2;
3204 int j;
3205 bool compat_road = FALSE;
3206 bool compat_rail = FALSE;
3207 bool compat_river = FALSE;
3208 const char **res;
3209 const char *filename = secfile_name(file);
3210 const char *text;
3211 int *res_freq;
3212 bool ok = TRUE;
3213
3214 /* parameters */
3215
3216 terrain_control.ocean_reclaim_requirement_pct
3217 = secfile_lookup_int_default(file, 101,
3218 "parameters.ocean_reclaim_requirement");
3219 terrain_control.land_channel_requirement_pct
3220 = secfile_lookup_int_default(file, 101,
3221 "parameters.land_channel_requirement");
3222 terrain_control.terrain_thaw_requirement_pct
3223 = secfile_lookup_int_default(file, 101,
3224 "parameters.thaw_requirement");
3225 terrain_control.terrain_freeze_requirement_pct
3226 = secfile_lookup_int_default(file, 101,
3227 "parameters.freeze_requirement");
3228 terrain_control.lake_max_size
3230 "parameters.lake_max_size");
3231 terrain_control.min_start_native_area
3233 "parameters.min_start_native_area");
3234 terrain_control.move_fragments
3236 "parameters.move_fragments");
3237 if (terrain_control.move_fragments < 1) {
3239 "\"%s\": move_fragments must be at least 1",
3240 filename);
3241 ok = FALSE;
3242 }
3244 terrain_control.igter_cost
3246 "parameters.igter_cost");
3247 if (terrain_control.igter_cost < 1) {
3249 "\"%s\": igter_cost must be at least 1",
3250 filename);
3251 ok = FALSE;
3252 }
3253 terrain_control.infrapoints = FALSE; /* This will be updated if we find
3254 * an placeable extra. */
3255
3256 terrain_control.pythagorean_diagonal
3258 "parameters.pythagorean_diagonal");
3259
3262 "parameters.ocean_resources");
3263
3264 text = secfile_lookup_str_default(file,
3265 N_("?gui_type:Build Type A Base"),
3266 "extraui.ui_name_base_fortress");
3267 sz_strlcpy(terrain_control.gui_type_base0, text);
3268
3269 text = secfile_lookup_str_default(file,
3270 N_("?gui_type:Build Type B Base"),
3271 "extraui.ui_name_base_airbase");
3272 sz_strlcpy(terrain_control.gui_type_base1, text);
3273
3274 if (ok) {
3275 /* Terrain details */
3276
3277 terrain_type_iterate(pterrain) {
3278 const char **slist;
3279 const int i = terrain_index(pterrain);
3280 const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
3281 const char *cstr;
3282 const char *ename;
3283
3284 sz_strlcpy(pterrain->graphic_str,
3285 secfile_lookup_str(file, "%s.graphic", tsection));
3286 sz_strlcpy(pterrain->graphic_alt,
3288 "%s.graphic_alt", tsection));
3289 sz_strlcpy(pterrain->graphic_alt2,
3291 "%s.graphic_alt2", tsection));
3292
3293 pterrain->identifier
3294 = secfile_lookup_str(file, "%s.identifier", tsection)[0];
3295 if ('\0' == pterrain->identifier) {
3297 "\"%s\" [%s] identifier missing value.",
3298 filename, tsection);
3299 ok = FALSE;
3300 break;
3301 }
3302 if (TERRAIN_UNKNOWN_IDENTIFIER == pterrain->identifier) {
3304 "\"%s\" [%s] cannot use '%c' as an identifier;"
3305 " it is reserved for unknown terrain.",
3306 filename, tsection, pterrain->identifier);
3307 ok = FALSE;
3308 break;
3309 }
3310 for (j = T_FIRST; j < i; j++) {
3311 if (pterrain->identifier == terrain_by_number(j)->identifier) {
3313 "\"%s\" [%s] has the same identifier as [%s].",
3314 filename, tsection,
3316 ok = FALSE;
3317 break;
3318 }
3319 }
3320
3321 if (!ok) {
3322 break;
3323 }
3324
3325 cstr = secfile_lookup_str(file, "%s.class", tsection);
3326 pterrain->tclass = terrain_class_by_name(cstr, fc_strcasecmp);
3327 if (!terrain_class_is_valid(pterrain->tclass)) {
3329 "\"%s\": [%s] unknown class \"%s\"",
3330 filename, tsection, cstr);
3331 ok = FALSE;
3332 break;
3333 }
3334
3335 if (!secfile_lookup_int(file, &pterrain->movement_cost,
3336 "%s.movement_cost", tsection)
3337 || !secfile_lookup_int(file, &pterrain->defense_bonus,
3338 "%s.defense_bonus", tsection)) {
3340 ok = FALSE;
3341 break;
3342 }
3343
3345 pterrain->output[o]
3346 = secfile_lookup_int_default(file, 0, "%s.%s", tsection,
3349
3350 res = secfile_lookup_str_vec(file, &nval, "%s.resources", tsection);
3352 "%s.resource_freq", tsection);
3353 if (nval2 > 0 && nval2 != nval) {
3355 "\"%s\": [%s] Different lengths for resources "
3356 "and resource frequencies",
3357 filename, tsection);
3358 ok = FALSE;
3359 }
3360 pterrain->resources = fc_calloc(nval + 1, sizeof(*pterrain->resources));
3361 pterrain->resource_freq = fc_calloc(nval + 1,
3362 sizeof(*pterrain->resource_freq));
3363 for (j = 0; j < nval; j++) {
3364 pterrain->resources[j] = lookup_resource(filename, res[j], tsection);
3365 if (pterrain->resources[j] == NULL) {
3366 ok = FALSE;
3367 break;
3368 }
3369 pterrain->resource_freq[j] = j < nval2
3370 ? res_freq[j]
3372 if (pterrain->resource_freq[j] < RESOURCE_FREQUENCY_MINIMUM
3373 || pterrain->resource_freq[j] > RESOURCE_FREQUENCY_MAXIMUM) {
3375 "\"%s\": [%s] Resource frequency '%d' "
3376 "outside allowed range",
3377 filename, tsection,
3378 pterrain->resource_freq[j]);
3379 ok = FALSE;
3380 break;
3381 }
3382 }
3383 pterrain->resources[nval] = NULL;
3384 /* Terminating zero technically not necessary */
3385 pterrain->resource_freq[nval] = 0;
3386 free(res);
3387 res = NULL;
3388 free(res_freq);
3389 res_freq = NULL;
3390
3391 if (!ok) {
3392 break;
3393 }
3394
3396 pterrain->road_output_incr_pct[o]
3397 = secfile_lookup_int_default(file, 0, "%s.road_%s_incr_pct",
3400
3401 if (!lookup_time(file, &pterrain->base_time, tsection, "base_time",
3402 filename, NULL, &ok)
3403 || !lookup_time(file, &pterrain->road_time, tsection, "road_time",
3404 filename, NULL, &ok)) {
3406 ok = FALSE;
3407 break;
3408 }
3409
3410 if (!lookup_terrain(file, "cultivate_result", filename, pterrain,
3411 &pterrain->cultivate_result, FALSE)) {
3412 ruleset_error(NULL, LOG_ERROR, "%s: No cultivate_result", tsection);
3413 ok = FALSE;
3414 break;
3415 }
3416 if (pterrain->cultivate_result == pterrain) {
3418 "%s: Cultivating result in terrain itself.",
3419 tsection);
3420 ok = FALSE;
3421 break;
3422 }
3423 if (!secfile_lookup_int(file, &pterrain->irrigation_food_incr,
3424 "%s.irrigation_food_incr", tsection)
3425 || !lookup_time(file, &pterrain->irrigation_time,
3426 tsection, "irrigation_time", filename, NULL, &ok)) {
3428 ok = FALSE;
3429 break;
3430 }
3431
3432 if (!lookup_terrain(file, "plant_result", filename, pterrain,
3433 &pterrain->plant_result, FALSE)) {
3434 ruleset_error(NULL, LOG_ERROR, "%s: No plant_result", tsection);
3435 ok = FALSE;
3436 break;
3437 }
3438 if (pterrain->plant_result == pterrain) {
3440 "%s: Planting result in terrain itself.",
3441 tsection);
3442 ok = FALSE;
3443 break;
3444 }
3445 if (!secfile_lookup_int(file, &pterrain->mining_shield_incr,
3446 "%s.mining_shield_incr", tsection)
3447 || !lookup_time(file, &pterrain->mining_time,
3448 tsection, "mining_time", filename, NULL, &ok)) {
3450 ok = FALSE;
3451 break;
3452 }
3453
3454 if (!lookup_time(file, &pterrain->cultivate_time,
3455 tsection, "cultivate_time", filename, NULL, &ok)) {
3457 "%s: Missing cultivate_time", tsection);
3458 ok = FALSE;
3459 break;
3460 }
3461 if ((pterrain->cultivate_result != NULL
3462 && pterrain->cultivate_time <= 0)
3463 || (pterrain->cultivate_result == NULL
3464 && pterrain->cultivate_time > 0)) {
3466 "%s: cultivate_result and cultivate_time disagree "
3467 "whether cultivating is enabled", tsection);
3468 ok = FALSE;
3469 break;
3470 }
3471
3472 if (!lookup_time(file, &pterrain->plant_time,
3473 tsection, "plant_time", filename, NULL, &ok)) {
3475 "%s: Missing plant_time", tsection);
3476 ok = FALSE;
3477 break;
3478 }
3479 if ((pterrain->plant_result != NULL
3480 && pterrain->plant_time <= 0)
3481 || (pterrain->plant_result == NULL
3482 && pterrain->plant_time > 0)) {
3484 "%s: plant_result and plant_time disagree "
3485 "whether planting is enabled", tsection);
3486 ok = FALSE;
3487 break;
3488 }
3489
3490 if (!lookup_unit_type(file, tsection, "animal",
3491 &pterrain->animal, filename,
3492 rule_name_get(&pterrain->name))) {
3493 ok = FALSE;
3494 break;
3495 }
3496
3497 if (!lookup_terrain(file, "transform_result", filename, pterrain,
3498 &pterrain->transform_result, TRUE)) {
3499 ok = FALSE;
3500 break;
3501 }
3502 if (!lookup_time(file, &pterrain->transform_time,
3503 tsection, "transform_time", filename, NULL, &ok)) {
3505 ok = FALSE;
3506 break;
3507 }
3508 if ((pterrain->transform_result != NULL
3509 && pterrain->transform_time <= 0)
3510 || (pterrain->transform_result == NULL
3511 && pterrain->transform_time > 0)) {
3513 "%s: transform_result and transform_time disagree "
3514 "whether transforming is enabled", tsection);
3515 ok = FALSE;
3516 break;
3517 }
3518
3519 pterrain->placing_time = 1; /* Default */
3520 lookup_time(file, &pterrain->placing_time,
3521 tsection, "placing_time", filename, NULL, &ok);
3522
3523 pterrain->pillage_time = 1; /* Default */
3524 lookup_time(file, &pterrain->pillage_time,
3525 tsection, "pillage_time", filename, NULL, &ok);
3526
3527 if (!lookup_terrain(file, "warmer_wetter_result", filename, pterrain,
3528 &pterrain->warmer_wetter_result, TRUE)
3529 || !lookup_terrain(file, "warmer_drier_result", filename, pterrain,
3530 &pterrain->warmer_drier_result, TRUE)
3531 || !lookup_terrain(file, "cooler_wetter_result", filename, pterrain,
3532 &pterrain->cooler_wetter_result, TRUE)
3533 || !lookup_terrain(file, "cooler_drier_result", filename, pterrain,
3534 &pterrain->cooler_drier_result, TRUE)) {
3535 ok = FALSE;
3536 break;
3537 }
3538
3539 /* Set default removal times */
3540 extra_type_iterate(pextra) {
3541 pterrain->extra_removal_times[extra_index(pextra)] = 0;
3543
3544 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
3545 if (!rscompat_terrain_extra_rmtime_3_2(file, tsection, pterrain)) {
3546 ok = FALSE;
3547 break;
3548 }
3549 }
3550
3551 for (j = 0; (ename = secfile_lookup_str_default(file, NULL,
3552 "%s.extra_settings%d.extra",
3553 tsection, j)); j++) {
3554 const struct extra_type *pextra = extra_type_by_rule_name(ename);
3555
3556 if (pextra != NULL) {
3557 char time_sections[512];
3558
3560 "%s.extra_settings%d", tsection, j);
3561
3562 lookup_time(file, &pterrain->extra_removal_times[extra_index(pextra)],
3563 time_sections, "removal_time", filename, NULL, &ok);
3564 } else {
3566 "\"%s\" [%s] has settings for unknown extra \"%s\".",
3567 filename, tsection, ename);
3568 ok = FALSE;
3569 break;
3570 }
3571 }
3572
3573 if (ok) {
3574 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsection);
3575 BV_CLR_ALL(pterrain->flags);
3576 for (j = 0; j < nval; j++) {
3577 const char *sval = slist[j];
3578 enum terrain_flag_id flag
3580
3581 if (!terrain_flag_id_is_valid(flag)) {
3583 "\"%s\" [%s] has unknown flag \"%s\".",
3584 filename, tsection, sval);
3585 ok = FALSE;
3586 break;
3587 } else {
3588 BV_SET(pterrain->flags, flag);
3589 }
3590 }
3591
3592 free(slist);
3593 }
3594
3595 if (!ok) {
3596 break;
3597 }
3598
3599 {
3601
3605 pterrain->property[mtp]
3606 = secfile_lookup_int_default(file, 0, "%s.property_%s", tsection,
3608 }
3609 }
3610
3611 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
3612 BV_CLR_ALL(pterrain->native_to);
3613 for (j = 0; j < nval; j++) {
3614 struct unit_class *class = unit_class_by_rule_name(slist[j]);
3615
3616 if (!class) {
3618 "\"%s\" [%s] is native to unknown unit class \"%s\".",
3619 filename, tsection, slist[j]);
3620 ok = FALSE;
3621 break;
3622 } else {
3623 BV_SET(pterrain->native_to, uclass_index(class));
3624 }
3625 }
3626 free(slist);
3627
3628 if (!ok) {
3629 break;
3630 }
3631
3632 /* Get terrain color */
3633 {
3634 fc_assert_ret_val(pterrain->rgb == NULL, FALSE);
3635
3636 if (!rgbcolor_load(file, &pterrain->rgb, "%s.color", tsection)) {
3638 "Missing terrain color definition: %s",
3639 secfile_error());
3640 ok = FALSE;
3641 break;
3642 }
3643 }
3644
3645 pterrain->helptext = lookup_strvec(file, tsection, "helptext");
3647 }
3648
3649 if (ok) {
3650 /* Extra details */
3651 extra_type_iterate(pextra) {
3652 BV_CLR_ALL(pextra->conflicts);
3654
3655 extra_type_iterate(pextra) {
3656 int eidx = extra_index(pextra);
3657 const char *section = &extra_sections[eidx * MAX_SECTION_LABEL];
3658 const char **slist;
3659 struct requirement_vector *reqs;
3660 const char *catname;
3661 int cj;
3662 enum extra_cause cause;
3664 const char *eus_name;
3665 const char *vis_req_name;
3666 const struct advance *vis_req;
3667
3668 catname = secfile_lookup_str(file, "%s.category", section);
3669 if (catname == NULL) {
3671 "\"%s\" extra \"%s\" has no category.",
3672 filename, extra_rule_name(pextra));
3673 ok = FALSE;
3674 break;
3675 }
3676 pextra->category = extra_category_by_name(catname, fc_strcasecmp);
3677 if (!extra_category_is_valid(pextra->category)) {
3679 "\"%s\" extra \"%s\" has invalid category \"%s\".",
3680 filename, extra_rule_name(pextra), catname);
3681 ok = FALSE;
3682 break;
3683 }
3684
3685 slist = secfile_lookup_str_vec(file, &nval, "%s.causes", section);
3686 pextra->causes = 0;
3687 for (cj = 0; cj < nval; cj++) {
3688 const char *sval = slist[cj];
3690
3691 if (!extra_cause_is_valid(cause)) {
3693 "\"%s\" extra \"%s\": unknown cause \"%s\".",
3694 filename, extra_rule_name(pextra), sval);
3695 ok = FALSE;
3696 break;
3697 } else {
3698 pextra->causes |= (1 << cause);
3699 extra_to_caused_by_list(pextra, cause);
3700 }
3701 }
3702
3703 if (pextra->causes == 0) {
3704 /* Extras that do not have any causes added to EC_NONE list */
3706 }
3707
3708 if (!is_extra_caused_by(pextra, EC_BASE)
3709 && !is_extra_caused_by(pextra, EC_ROAD)
3710 && !is_extra_caused_by(pextra, EC_RESOURCE)) {
3711 /* Not a base, road, nor resource, so special */
3712 pextra->data.special_idx = extra_type_list_size(extra_type_list_by_cause(EC_SPECIAL));
3714 }
3715
3716 free(slist);
3717
3718 /* Handle before rscompat_extra_rmcause_3_2() might need the values */
3719 pextra->removal_time = 0; /* Default */
3720 lookup_time(file, &pextra->removal_time, section, "removal_time",
3721 filename, extra_rule_name(pextra), &ok);
3722 pextra->removal_time_factor
3723 = secfile_lookup_int_default(file, 1, "%s.removal_time_factor",
3724 section);
3725
3726 /* Do not clear after this point.
3727 * rscompat_extra_rmcause_3_2() might set a flag we want to keep. */
3728 BV_CLR_ALL(pextra->flags);
3729
3730 slist = secfile_lookup_str_vec(file, &nval, "%s.rmcauses", section);
3731 pextra->rmcauses = 0;
3732 for (j = 0; j < nval; j++) {
3733 const char *sval = slist[j];
3734
3735 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
3737 }
3738
3740
3743 "\"%s\" extra \"%s\": unknown rmcause \"%s\".",
3744 filename, extra_rule_name(pextra), sval);
3745 ok = FALSE;
3746 break;
3747 } else {
3748 pextra->rmcauses |= (1 << rmcause);
3750 }
3751 }
3752
3753 free(slist);
3754
3755 sz_strlcpy(pextra->activity_gfx,
3757 "%s.activity_gfx", section));
3758 sz_strlcpy(pextra->act_gfx_alt,
3760 "%s.act_gfx_alt", section));
3761 sz_strlcpy(pextra->act_gfx_alt2,
3763 "%s.act_gfx_alt2", section));
3764 sz_strlcpy(pextra->rmact_gfx,
3766 "%s.rmact_gfx", section));
3767 sz_strlcpy(pextra->rmact_gfx_alt,
3769 "%s.rmact_gfx_alt", section));
3770 sz_strlcpy(pextra->rmact_gfx_alt2,
3772 "%s.rmact_gfx_alt2", section));
3773 sz_strlcpy(pextra->graphic_str,
3774 secfile_lookup_str_default(file, "-", "%s.graphic", section));
3775 sz_strlcpy(pextra->graphic_alt,
3777 "%s.graphic_alt", section));
3778
3779 reqs = lookup_req_list(file, compat, section, "reqs", extra_rule_name(pextra));
3780 if (reqs == NULL) {
3781 ok = FALSE;
3782 break;
3783 }
3784 requirement_vector_copy(&pextra->reqs, reqs);
3785
3786 reqs = lookup_req_list(file, compat, section, "rmreqs", extra_rule_name(pextra));
3787 if (reqs == NULL) {
3788 ok = FALSE;
3789 break;
3790 }
3791 requirement_vector_copy(&pextra->rmreqs, reqs);
3792
3793 reqs = lookup_req_list(file, compat, section, "appearance_reqs", extra_rule_name(pextra));
3794 if (reqs == NULL) {
3795 ok = FALSE;
3796 break;
3797 }
3798 requirement_vector_copy(&pextra->appearance_reqs, reqs);
3799
3800 reqs = lookup_req_list(file, compat, section, "disappearance_reqs", extra_rule_name(pextra));
3801 if (reqs == NULL) {
3802 ok = FALSE;
3803 break;
3804 }
3805 requirement_vector_copy(&pextra->disappearance_reqs, reqs);
3806
3807 pextra->buildable = secfile_lookup_bool_default(file,
3809 "%s.buildable", section);
3810 pextra->generated = secfile_lookup_bool_default(file, TRUE,
3811 "%s.generated", section);
3812
3813 pextra->build_time = 0; /* Default */
3814 lookup_time(file, &pextra->build_time, section, "build_time",
3815 filename, extra_rule_name(pextra), &ok);
3816 pextra->build_time_factor = secfile_lookup_int_default(file, 1,
3817 "%s.build_time_factor", section);
3818
3819 /* removal_time handled earlier, so that rscompat_extra_rmcause_3_2()
3820 * can use them. */
3821
3822 pextra->infracost = secfile_lookup_int_default(file, 0,
3823 "%s.infracost", section);
3824 if (pextra->infracost > 0) {
3825 terrain_control.infrapoints = TRUE;
3826 }
3827
3828 pextra->defense_bonus = secfile_lookup_int_default(file, 0,
3829 "%s.defense_bonus",
3830 section);
3831 if (pextra->defense_bonus != 0) {
3832 if (extra_has_flag(pextra, EF_NATURAL_DEFENSE)) {
3834 } else {
3836 }
3837 }
3838
3839 eus_name = secfile_lookup_str_default(file, "Normal", "%s.unit_seen", section);
3841 if (!extra_unit_seen_type_is_valid(pextra->eus)) {
3843 "\"%s\" extra \"%s\" has illegal unit_seen value \"%s\".",
3844 filename, extra_rule_name(pextra), eus_name);
3845 ok = FALSE;
3846 break;
3847 }
3848 if (pextra->eus == EUS_HIDDEN) {
3850 }
3851
3852 pextra->appearance_chance = secfile_lookup_int_default(file, RS_DEFAULT_EXTRA_APPEARANCE,
3853 "%s.appearance_chance",
3854 section);
3855 pextra->disappearance_chance = secfile_lookup_int_default(file,
3857 "%s.disappearance_chance",
3858 section);
3859
3860 pextra->no_aggr_near_city = secfile_lookup_int_default(file, -1,
3861 "%s.no_aggr_near_city",
3862 section);
3863
3864 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
3865 BV_CLR_ALL(pextra->native_to);
3866 for (j = 0; j < nval; j++) {
3867 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
3868
3869 if (uclass == NULL) {
3871 "\"%s\" extra \"%s\" is native to unknown unit class \"%s\".",
3872 filename, extra_rule_name(pextra), slist[j]);
3873 ok = FALSE;
3874 break;
3875 } else {
3876 BV_SET(pextra->native_to, uclass_index(uclass));
3877 }
3878 }
3879 free(slist);
3880
3881 if (!ok) {
3882 break;
3883 }
3884
3885 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
3886 for (j = 0; j < nval; j++) {
3887 const char *sval = slist[j];
3888 enum extra_flag_id flag;
3889
3890 if (compat->compat_mode && compat->version < RSFORMAT_3_2
3891 && !fc_strcasecmp("NoAggressive", sval)) {
3892 if (pextra->no_aggr_near_city >= 0) {
3894 "\"%s\" extra \"%s\" has both no_aggr_near_city set and old style "
3895 "NoAggressive flag",
3896 filename, extra_rule_name(pextra));
3897 ok = FALSE;
3898 break;
3899 }
3900 /* Old NoAggressive flag meant distance of 3. */
3901 pextra->no_aggr_near_city = 3;
3902 } else {
3903
3905
3906 if (!extra_flag_id_is_valid(flag)) {
3908 "\"%s\" extra \"%s\": unknown flag \"%s\".",
3909 filename, extra_rule_name(pextra), sval);
3910 ok = FALSE;
3911 break;
3912 } else {
3913 BV_SET(pextra->flags, flag);
3914 }
3915 }
3916 }
3917 free(slist);
3918
3919 if (pextra->no_aggr_near_city >= 0) {
3921 }
3922
3923 if (extra_has_flag(pextra, EF_CAUSE_ZOC)) {
3925 }
3926
3927 if (!ok) {
3928 break;
3929 }
3930
3931 slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
3932 for (j = 0; j < nval; j++) {
3933 const char *sval = slist[j];
3935
3936 if (pextra2 == NULL) {
3938 "\"%s\" extra \"%s\": unknown conflict extra \"%s\".",
3939 filename, extra_rule_name(pextra), sval);
3940 ok = FALSE;
3941 break;
3942 } else {
3943 BV_SET(pextra->conflicts, extra_index(pextra2));
3944 BV_SET(pextra2->conflicts, extra_index(pextra));
3945 }
3946 }
3947
3948 free(slist);
3949
3950 if (!ok) {
3951 break;
3952 }
3953
3954 slist = secfile_lookup_str_vec(file, &nval, "%s.hidden_by", section);
3955 BV_CLR_ALL(pextra->hidden_by);
3956 for (j = 0; j < nval; j++) {
3957 const char *sval = slist[j];
3958 const struct extra_type *top = extra_type_by_rule_name(sval);
3959
3960 if (top == NULL) {
3962 "\"%s\" extra \"%s\" hidden by unknown extra \"%s\".",
3963 filename, extra_rule_name(pextra), sval);
3964 ok = FALSE;
3965 break;
3966 } else {
3967 BV_SET(pextra->hidden_by, extra_index(top));
3968 }
3969 }
3970 free(slist);
3971
3972 if (!ok) {
3973 break;
3974 }
3975
3976 slist = secfile_lookup_str_vec(file, &nval, "%s.bridged_over", section);
3977 BV_CLR_ALL(pextra->bridged_over);
3978 for (j = 0; j < nval; j++) {
3979 const char *sval = slist[j];
3980 const struct extra_type *top = extra_type_by_rule_name(sval);
3981
3982 if (top == NULL) {
3984 "\"%s\" extra \"%s\" bridged over unknown extra \"%s\".",
3985 filename, extra_rule_name(pextra), sval);
3986 ok = FALSE;
3987 break;
3988 } else {
3989 BV_SET(pextra->bridged_over, extra_index(top));
3990 }
3991 }
3992 free(slist);
3993
3994 if (!ok) {
3995 break;
3996 }
3997
3999 "%s.visibility_req", section);
4001
4002 if (vis_req == NULL) {
4004 "\"%s\" %s: unknown visibility_req %s.",
4005 filename, section, vis_req_name);
4006 ok = FALSE;
4007 break;
4008 }
4009
4010 pextra->visibility_req = advance_number(vis_req);
4011
4012 pextra->helptext = lookup_strvec(file, section, "helptext");
4013
4014 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
4016 }
4018 }
4019
4020 if (ok) {
4021 int i = 0;
4022 /* Resource details */
4023
4025 char identifier[MAX_LEN_NAME];
4026 const char *id;
4028
4029 if (!presource->data.resource) {
4031 "\"%s\" extra \"%s\" has \"Resource\" cause but no "
4032 "corresponding [resource_*] section",
4033 filename, extra_rule_name(presource));
4034 ok = FALSE;
4035 break;
4036 }
4037
4039 presource->data.resource->output[o] =
4040 secfile_lookup_int_default(file, 0, "%s.%s", rsection,
4043
4044 id = secfile_lookup_str_default(file, NULL, "%s.identifier", rsection);
4045
4046 if (id == NULL) {
4047 presource->data.resource->id_old_save = '\0';
4048 } else {
4049 sz_strlcpy(identifier, id);
4050
4051 presource->data.resource->id_old_save = identifier[0];
4052 if (RESOURCE_NULL_IDENTIFIER == presource->data.resource->id_old_save) {
4054 "\"%s\" [%s] identifier missing value.",
4055 filename, rsection);
4056 ok = FALSE;
4057 break;
4058 }
4059 if (RESOURCE_NONE_IDENTIFIER == presource->data.resource->id_old_save) {
4061 "\"%s\" [%s] cannot use '%c' as an identifier;"
4062 " it is reserved.",
4063 filename, rsection, presource->data.resource->id_old_save);
4064 ok = FALSE;
4065 break;
4066 }
4067 }
4068
4069 if (!ok) {
4070 break;
4071 }
4072
4073 i++;
4075
4076 for (j = 0; ok && j < game.control.num_resource_types; j++) {
4077 const char *section = &resource_sections[j * MAX_SECTION_LABEL];
4078 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4080
4081 if (!is_extra_caused_by(pextra, EC_RESOURCE)) {
4083 "\"%s\" resource section [%s]: extra \"%s\" does not "
4084 "have \"Resource\" in its causes",
4085 filename, section, extra_name);
4086 ok = FALSE;
4087 }
4088 }
4089 }
4090
4091 if (ok) {
4092 /* This can't be part of previous loop as we don't want random data from previous
4093 * ruleset to play havoc on us when we have only some resource identifiers loaded
4094 * from the new ruleset. */
4096 if (pres->data.resource->id_old_save != '\0') {
4098 if (pres->data.resource->id_old_save == pres2->data.resource->id_old_save
4099 && pres != pres2) {
4101 "\"%s\" [%s] has the same identifier as [%s].",
4102 filename,
4105 ok = FALSE;
4106 break;
4107 }
4109
4110 if (!ok) {
4111 break;
4112 }
4113 }
4115 }
4116
4117 if (ok) {
4118 /* Base details */
4120 struct base_type *pbase = extra_base_get(pextra);
4121 const char *section;
4122 const char *gui_str;
4123
4124 if (!pbase) {
4126 "\"%s\" extra \"%s\" has \"Base\" cause but no "
4127 "corresponding [base_*] section",
4128 filename, extra_rule_name(pextra));
4129 ok = FALSE;
4130 break;
4131 }
4133
4134 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4136 if (!base_gui_type_is_valid(pbase->gui_type)) {
4138 "\"%s\" base \"%s\": unknown gui_type \"%s\".",
4139 filename, extra_rule_name(pextra), gui_str);
4140 ok = FALSE;
4141 break;
4142 }
4143
4144 pbase->border_sq = secfile_lookup_int_default(file, -1, "%s.border_sq",
4145 section);
4146 pbase->vision_main_sq = secfile_lookup_int_default(file, -1,
4147 "%s.vision_main_sq",
4148 section);
4149 pbase->vision_invis_sq = secfile_lookup_int_default(file, -1,
4150 "%s.vision_invis_sq",
4151 section);
4152 pbase->vision_subs_sq = secfile_lookup_int_default(file, -1,
4153 "%s.vision_subs_sq",
4154 section);
4155
4156 if (!ok) {
4157 break;
4158 }
4159
4162
4164 struct base_type *pbase2;
4165
4166 if (pextra == pextra2) {
4167 /* End of the fully initialized bases iteration. */
4168 break;
4169 }
4170
4173 BV_SET(pextra->conflicts, extra_index(pextra2));
4174 BV_SET(pextra2->conflicts, extra_index(pextra));
4175 }
4177 }
4179
4180 for (j = 0; ok && j < game.control.num_base_types; j++) {
4181 const char *section = &base_sections[j * MAX_SECTION_LABEL];
4182 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4184
4185 if (!is_extra_caused_by(pextra, EC_BASE)) {
4187 "\"%s\" base section [%s]: extra \"%s\" does not have "
4188 "\"Base\" in its causes",
4189 filename, section, extra_name);
4190 ok = FALSE;
4191 }
4192 }
4193 }
4194
4195 if (ok) {
4197 struct road_type *proad = extra_road_get(pextra);
4198 const char *section;
4199 const char **slist;
4200 const char *special;
4201 const char *modestr;
4202 struct requirement_vector *reqs;
4203 const char *gui_str;
4204
4205 if (!proad) {
4207 "\"%s\" extra \"%s\" has \"Road\" cause but no "
4208 "corresponding [road_*] section",
4209 filename, extra_rule_name(pextra));
4210 ok = FALSE;
4211 break;
4212 }
4214
4215 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4217 if (!road_gui_type_is_valid(proad->gui_type)) {
4219 "\"%s\" road \"%s\": unknown gui_type \"%s\".",
4220 filename, extra_rule_name(pextra), gui_str);
4221 ok = FALSE;
4222 break;
4223 }
4224
4225 reqs = lookup_req_list(file, compat, section, "first_reqs", extra_rule_name(pextra));
4226 if (reqs == NULL) {
4227 ok = FALSE;
4228 break;
4229 }
4230 requirement_vector_copy(&proad->first_reqs, reqs);
4231
4232 if (!secfile_lookup_int(file, &proad->move_cost,
4233 "%s.move_cost", section)) {
4234 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4235 ok = FALSE;
4236 break;
4237 }
4238
4239 modestr = secfile_lookup_str_default(file, "FastAlways", "%s.move_mode",
4240 section);
4242 if (!road_move_mode_is_valid(proad->move_mode)) {
4244 "Illegal move_mode \"%s\" for road \"%s\"",
4245 modestr, extra_rule_name(pextra));
4246 ok = FALSE;
4247 break;
4248 }
4249
4251 proad->tile_incr_const[o] =
4252 secfile_lookup_int_default(file, 0, "%s.%s_incr_const",
4254 proad->tile_incr[o] =
4255 secfile_lookup_int_default(file, 0, "%s.%s_incr",
4257 proad->tile_bonus[o] =
4258 secfile_lookup_int_default(file, 0, "%s.%s_bonus",
4261
4262 special = secfile_lookup_str_default(file, "None", "%s.compat_special", section);
4263 if (!fc_strcasecmp(special, "Road")) {
4264 if (compat_road) {
4266 "Multiple roads marked as compatibility \"Road\"");
4267 ok = FALSE;
4268 }
4269 compat_road = TRUE;
4270 proad->compat = ROCO_ROAD;
4271 } else if (!fc_strcasecmp(special, "Railroad")) {
4272 if (compat_rail) {
4274 "Multiple roads marked as compatibility \"Railroad\"");
4275 ok = FALSE;
4276 }
4277 compat_rail = TRUE;
4278 proad->compat = ROCO_RAILROAD;
4279 } else if (!fc_strcasecmp(special, "River")) {
4280 if (compat_river) {
4282 "Multiple roads marked as compatibility \"River\"");
4283 ok = FALSE;
4284 }
4286 proad->compat = ROCO_RIVER;
4287 } else if (!fc_strcasecmp(special, "None")) {
4288 proad->compat = ROCO_NONE;
4289 } else {
4291 "Illegal compatibility special \"%s\" for road %s",
4292 special, extra_rule_name(pextra));
4293 ok = FALSE;
4294 }
4295
4296 if (!ok) {
4297 break;
4298 }
4299
4300 slist = secfile_lookup_str_vec(file, &nval, "%s.integrates", section);
4301 BV_CLR_ALL(proad->integrates);
4302 for (j = 0; j < nval; j++) {
4303 const char *sval = slist[j];
4305 struct road_type *top = NULL;
4306
4307 if (textra != NULL) {
4308 top = extra_road_get(textra);
4309 }
4310
4311 if (top == NULL) {
4313 "\"%s\" road \"%s\" integrates with unknown road \"%s\".",
4314 filename, extra_rule_name(pextra), sval);
4315 ok = FALSE;
4316 break;
4317 } else {
4318 BV_SET(proad->integrates, road_number(top));
4319 }
4320 }
4321 free(slist);
4322
4323 if (!ok) {
4324 break;
4325 }
4326
4327 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
4328 BV_CLR_ALL(proad->flags);
4329 for (j = 0; j < nval; j++) {
4330 const char *sval = slist[j];
4332
4333 if (!road_flag_id_is_valid(flag)) {
4335 "\"%s\" road \"%s\": unknown flag \"%s\".",
4336 filename, extra_rule_name(pextra), sval);
4337 ok = FALSE;
4338 break;
4339 } else {
4340 BV_SET(proad->flags, flag);
4341 }
4342 }
4343 free(slist);
4344
4345 if (!ok) {
4346 break;
4347 }
4349
4350 for (j = 0; ok && j < game.control.num_road_types; j++) {
4351 const char *section = &road_sections[j * MAX_SECTION_LABEL];
4352 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4354
4355 if (!is_extra_caused_by(pextra, EC_ROAD)) {
4357 "\"%s\" road section [%s]: extra \"%s\" does not have "
4358 "\"Road\" in its causes",
4359 filename, section, extra_name);
4360 ok = FALSE;
4361 }
4362 }
4363 }
4364
4365 if (ok) {
4366 extra_type_iterate(pextra) {
4367 pextra->bridged = extra_type_list_new();
4369 if (BV_ISSET(pextra->bridged_over, pbridged->id)) {
4370 extra_type_list_append(pextra->bridged, pbridged);
4371 }
4374 }
4375
4376 if (ok) {
4378 }
4379
4380 return ok;
4381}
4382
4383/**********************************************************************/
4387static bool load_government_names(struct section_file *file,
4388 struct rscompat_info *compat)
4389{
4390 int nval = 0;
4391 struct section_list *sec;
4392 const char *filename = secfile_name(file);
4393 bool ok = TRUE;
4394
4395 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4396 return FALSE;
4397 }
4398
4399 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4400 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4401
4403 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
4404 ruleset_error(NULL, LOG_ERROR, "\"%s\": No governments?!?", filename);
4405 ok = FALSE;
4406 } else if (nval > G_LAST) {
4408 "\"%s\": Too many governments (%d, max %d)",
4409 filename, nval, G_LAST);
4410 ok = FALSE;
4411 }
4412
4413 if (ok) {
4415
4416 /* Government names are needed early so that get_government_by_name will
4417 * work. */
4418 governments_iterate(gov) {
4419 const char *sec_name =
4421
4422 if (!ruleset_load_names(&gov->name, NULL, file, sec_name)) {
4423 ok = FALSE;
4424 break;
4425 }
4427 }
4428
4430
4431 if (ok) {
4433 nval = (NULL != sec ? section_list_size(sec) : 0);
4434
4435 if (nval > MAX_NUM_MULTIPLIERS) {
4437 "\"%s\": Too many multipliers (%d, max %d)",
4438 filename, nval, MAX_NUM_MULTIPLIERS);
4439
4440 ok = FALSE;
4441 } else {
4443 }
4444
4445 if (ok) {
4446 multipliers_iterate(pmul) {
4447 const char *sec_name =
4449
4450 if (!ruleset_load_names(&pmul->name, NULL, file, sec_name)) {
4452 "\"%s\": Cannot load multiplier names",
4453 filename);
4454 ok = FALSE;
4455 break;
4456 }
4458 }
4459 }
4460
4462
4463 return ok;
4464}
4465
4466/**********************************************************************/
4470 struct rscompat_info *compat)
4471{
4472 struct section_list *sec;
4473 const char *filename = secfile_name(file);
4474 bool ok = TRUE;
4475
4477
4479 = lookup_government(file, "governments.during_revolution", filename, NULL);
4481 ok = FALSE;
4482 }
4483
4484 if (ok) {
4487
4488 /* Easy ones: */
4490 const int i = government_index(g);
4491 const char *sec_name = section_name(section_list_get(sec, i));
4492 struct requirement_vector *reqs
4494
4495 if (reqs == NULL) {
4496 ok = FALSE;
4497 break;
4498 }
4499
4500 if (NULL != secfile_entry_lookup(file, "%s.ai_better", sec_name)) {
4501 char entry[100];
4502
4503 fc_snprintf(entry, sizeof(entry), "%s.ai_better", sec_name);
4504 g->ai.better = lookup_government(file, entry, filename, NULL);
4505 if (g->ai.better == NULL) {
4506 ok = FALSE;
4507 break;
4508 }
4509 } else {
4510 g->ai.better = NULL;
4511 }
4512 requirement_vector_copy(&g->reqs, reqs);
4513
4514 sz_strlcpy(g->graphic_str,
4515 secfile_lookup_str(file, "%s.graphic", sec_name));
4516 sz_strlcpy(g->graphic_alt,
4517 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
4518 sz_strlcpy(g->sound_str,
4519 secfile_lookup_str_default(file, "-", "%s.sound", sec_name));
4520 sz_strlcpy(g->sound_alt,
4521 secfile_lookup_str_default(file, "-", "%s.sound_alt", sec_name));
4522 sz_strlcpy(g->sound_alt2,
4523 secfile_lookup_str_default(file, "-", "%s.sound_alt2", sec_name));
4524
4525 g->helptext = lookup_strvec(file, sec_name, "helptext");
4527 }
4528
4529
4530 if (ok) {
4531 /* Titles */
4533 const char *sec_name
4535 const char *male, *female;
4536
4537 if (!(male = secfile_lookup_str(file, "%s.ruler_male_title", sec_name))
4538 || !(female = secfile_lookup_str(file, "%s.ruler_female_title",
4539 sec_name))) {
4541 "Lack of default ruler titles for "
4542 "government \"%s\" (nb %d): %s",
4544 secfile_error());
4545 ok = FALSE;
4546 break;
4547 } else if (NULL == government_ruler_title_new(g, NULL, male, female)) {
4549 "Lack of default ruler titles for "
4550 "government \"%s\" (nb %d).",
4552 ok = FALSE;
4553 break;
4554 }
4556 }
4557
4559
4560 if (ok) {
4562 multipliers_iterate(pmul) {
4563 int id = multiplier_index(pmul);
4564 const char *sec_name = section_name(section_list_get(sec, id));
4565 struct requirement_vector *reqs;
4566
4567 if (!secfile_lookup_int(file, &pmul->start, "%s.start", sec_name)) {
4568 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4569 ok = FALSE;
4570 break;
4571 }
4572 if (!secfile_lookup_int(file, &pmul->stop, "%s.stop", sec_name)) {
4573 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4574 ok = FALSE;
4575 break;
4576 }
4577 if (pmul->stop <= pmul->start) {
4579 "Multiplier \"%s\" stop (%d) must be greater "
4580 "than start (%d)", multiplier_rule_name(pmul),
4581 pmul->stop, pmul->start);
4582 ok = FALSE;
4583 break;
4584 }
4585 if (!secfile_lookup_int(file, &pmul->step, "%s.step", sec_name)) {
4586 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4587 ok = FALSE;
4588 break;
4589 }
4590 if (((pmul->stop - pmul->start) % pmul->step) != 0) {
4592 "Multiplier \"%s\" step (%d) does not fit "
4593 "exactly into interval start-stop (%d to %d)",
4594 multiplier_rule_name(pmul), pmul->step,
4595 pmul->start, pmul->stop);
4596 ok = FALSE;
4597 break;
4598 }
4599 if (!secfile_lookup_int(file, &pmul->def, "%s.default", sec_name)) {
4600 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4601 ok = FALSE;
4602 break;
4603 }
4604 if (pmul->def < pmul->start || pmul->def > pmul->stop) {
4606 "Multiplier \"%s\" default (%d) not within "
4607 "legal range (%d to %d)", multiplier_rule_name(pmul),
4608 pmul->def, pmul->start, pmul->stop);
4609 ok = FALSE;
4610 break;
4611 }
4612 if (((pmul->def - pmul->start) % pmul->step) != 0) {
4614 "Multiplier \"%s\" default (%d) not legal "
4615 "with respect to step size %d",
4616 multiplier_rule_name(pmul), pmul->def, pmul->step);
4617 ok = FALSE;
4618 break;
4619 }
4620 pmul->offset = secfile_lookup_int_default(file, 0,
4621 "%s.offset", sec_name);
4622 pmul->factor = secfile_lookup_int_default(file, 100,
4623 "%s.factor", sec_name);
4624 if (pmul->factor == 0) {
4626 "Multiplier \"%s\" scaling factor must "
4627 "not be zero", multiplier_rule_name(pmul));
4628 ok = FALSE;
4629 break;
4630 }
4631
4632 pmul->minimum_turns = secfile_lookup_int_default(file, 0,
4633 "%s.minimum_turns",
4634 sec_name);
4635
4636 reqs = lookup_req_list(file, compat, sec_name, "reqs",
4637 multiplier_rule_name(pmul));
4638 if (reqs == NULL) {
4639 ok = FALSE;
4640 break;
4641 }
4642 requirement_vector_copy(&pmul->reqs, reqs);
4643
4644 pmul->helptext = lookup_strvec(file, sec_name, "helptext");
4647 }
4648
4649 if (ok) {
4651 }
4652
4653 return ok;
4654}
4655
4656/**********************************************************************/
4667static void send_ruleset_control(struct conn_list *dest)
4668{
4670 int idx = 0;
4671
4673
4674 if (game.ruleset_summary != NULL) {
4675 struct packet_ruleset_summary summary;
4676
4678
4679 lsend_packet_ruleset_summary(dest, &summary);
4680 }
4681
4682 while (desc_left > 0) {
4684 int this_len = desc_left;
4685
4686 if (this_len > MAX_LEN_CONTENT - 21) {
4688 }
4689
4690 part.text[this_len] = '\0';
4691
4693 idx += this_len;
4695
4697 }
4698}
4699
4700/**********************************************************************/
4705static const char *check_leader_names(struct nation_type *pnation)
4706{
4708 const char *name = nation_leader_name(pleader);
4709
4711 if (prev_leader == pleader) {
4712 break;
4713 } else if (0 == fc_strcasecmp(name, nation_leader_name(prev_leader))) {
4714 return name;
4715 }
4718 return NULL;
4719}
4720
4721/**********************************************************************/
4725static bool load_nation_names(struct section_file *file,
4726 struct rscompat_info *compat)
4727{
4728 struct section_list *sec;
4729 int j;
4730 bool ok = TRUE;
4731 const char *filename = secfile_name(file);
4732
4733 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4734 return FALSE;
4735 }
4736
4737 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4738 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4739
4741 if (NULL == sec) {
4743 "No available nations in this ruleset!");
4744 ok = FALSE;
4745 } else if (section_list_size(sec) > MAX_NUM_NATIONS) {
4747 "Too many nations (max %d, we have %d)!",
4749 ok = FALSE;
4750 } else {
4753
4755 const int i = nation_index(pl);
4756 const char *sec_name = section_name(section_list_get(sec, i));
4757 const char *domain = secfile_lookup_str_default(file, NULL,
4758 "%s.translation_domain", sec_name);
4759 const char *noun_plural = secfile_lookup_str(file,
4760 "%s.plural", sec_name);
4761
4762
4763 if (domain == NULL) {
4764 domain = "freeciv-nations";
4765 }
4766
4767 if (!strcmp("freeciv-core", domain)) {
4768 pl->translation_domain = NULL;
4769 } else if (!strcmp("freeciv-nations", domain)) {
4770 pl->translation_domain = fc_strdup(domain);
4771 } else {
4773 "Unsupported translation domain \"%s\" for %s",
4774 domain, sec_name);
4775 ok = FALSE;
4776 break;
4777 }
4778
4779 if (!ruleset_load_names(&pl->adjective, pl->translation_domain, file, sec_name)) {
4780 ok = FALSE;
4781 break;
4782 }
4783 name_set(&pl->noun_plural, pl->translation_domain, noun_plural);
4784
4785 /* Check if nation name is already defined. */
4786 for (j = 0; j < i && ok; j++) {
4787 struct nation_type *n2 = nation_by_number(j);
4788
4789 /* Compare strings after stripping off qualifiers -- we don't want
4790 * two nations to end up with identical adjectives displayed to users.
4791 * (This check only catches English, not localisations, of course.) */
4792 if (0 == strcmp(Qn_(untranslated_name(&n2->adjective)),
4793 Qn_(untranslated_name(&pl->adjective)))) {
4795 "Two nations defined with the same adjective \"%s\": "
4796 "in section \'%s\' and section \'%s\'",
4797 Qn_(untranslated_name(&pl->adjective)),
4799 ok = FALSE;
4800 } else if (!strcmp(rule_name_get(&n2->adjective),
4801 rule_name_get(&pl->adjective))) {
4802 /* We cannot have the same rule name, as the game needs them to be
4803 * distinct. */
4805 "Two nations defined with the same rule_name \"%s\": "
4806 "in section \'%s\' and section \'%s\'",
4807 rule_name_get(&pl->adjective),
4809 ok = FALSE;
4810 } else if (0 == strcmp(Qn_(untranslated_name(&n2->noun_plural)),
4811 Qn_(untranslated_name(&pl->noun_plural)))) {
4812 /* We don't want identical English plural names either. */
4814 "Two nations defined with the same plural name \"%s\": "
4815 "in section \'%s\' and section \'%s\'",
4816 Qn_(untranslated_name(&pl->noun_plural)),
4818 ok = FALSE;
4819 }
4820 }
4821 if (!ok) {
4822 break;
4823 }
4825 }
4826
4828
4829 if (ok) {
4831 if (sec != NULL) {
4833
4834 section_list_iterate(sec, psection) {
4835 struct nation_group *pgroup;
4836 const char *name;
4837
4838 name = secfile_lookup_str(file, "%s.name", section_name(psection));
4839 if (NULL == name) {
4840 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4841 ok = FALSE;
4842 break;
4843 }
4845 if (pgroup == NULL) {
4846 ok = FALSE;
4847 break;
4848 }
4851 sec = NULL;
4852 }
4853 }
4854
4855 return ok;
4856}
4857
4858/**********************************************************************/
4861static bool is_on_allowed_list(const char *name, const char **list, size_t len)
4862{
4863 int i;
4864
4865 for (i = 0; i < len; i++) {
4866 if (!fc_strcasecmp(name, list[i])) {
4867 return TRUE;
4868 }
4869 }
4870 return FALSE;
4871}
4872
4873/**********************************************************************/
4877static bool load_city_name_list(struct section_file *file,
4878 struct nation_type *pnation,
4879 const char *secfile_str1,
4880 const char *secfile_str2,
4881 const char **allowed_terrains,
4882 size_t atcount)
4883{
4884 size_t dim, j;
4885 bool ok = TRUE;
4886 const char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
4888
4889 /* Each string will be of the form "<cityname> (<label>, <label>, ...)".
4890 * The cityname is just the name for this city, while each "label" matches
4891 * a terrain type for the city (or "river"), with a preceding ! to negate
4892 * it. The parentheses are optional (but necessary to have the settings,
4893 * of course). Our job is now to parse it. */
4894 for (j = 0; j < dim; j++) {
4895 size_t len = strlen(cities[j]);
4896 char city_name[len + 1], *p, *next, *end;
4897 struct nation_city *pncity;
4898
4900
4901 /* Now we wish to determine values for all of the city labels. A value
4902 * of NCP_NONE means no preference (which is necessary so that the use
4903 * of this is optional); NCP_DISLIKE means the label is negated and
4904 * NCP_LIKE means it's labelled. Mostly the parsing just involves
4905 * a lot of ugly string handling... */
4906 if ((p = strchr(city_name, '('))) {
4907 *p++ = '\0';
4908
4909 if (!(end = strchr(p, ')'))) {
4911 "\"%s\" [%s] %s: city name \"%s\" "
4912 "unmatched parenthesis.", secfile_name(file),
4914 ok = FALSE;
4915 } else {
4916 for (*end++ = '\0'; '\0' != *end; end++) {
4917 if (!fc_isspace(*end)) {
4919 "\"%s\" [%s] %s: city name \"%s\" "
4920 "contains characters after last parenthesis.",
4922 cities[j]);
4923 ok = FALSE;
4924 break;
4925 }
4926 }
4927 }
4928 }
4929
4930 /* Build the nation_city. */
4933 /* The ruleset contains a name that is too long. This shouldn't
4934 * happen - if it does, the author should get immediate feedback. */
4936 "\"%s\" [%s] %s: city name \"%s\" is too long.",
4937 secfile_name(file),
4939 ok = FALSE;
4940 city_name[MAX_LEN_CITYNAME - 1] = '\0';
4941 }
4942 pncity = nation_city_new(pnation, city_name);
4943
4944 if (NULL != p) {
4945 /* Handle the labels one at a time. */
4946 do {
4947 enum nation_city_preference prefer;
4948
4949 if ((next = strchr(p, ','))) {
4950 *next = '\0';
4951 }
4953
4954 /* The ! is used to mark a negative, which is recorded with
4955 * NCP_DISLIKE. Otherwise we use a NCP_LIKE.
4956 */
4957 if (*p == '!') {
4958 p++;
4959 prefer = NCP_DISLIKE;
4960 } else {
4961 prefer = NCP_LIKE;
4962 }
4963
4964 if (0 == fc_strcasecmp(p, "river")) {
4966 && !is_on_allowed_list(p,
4969 "\"%s\" [%s] %s: city \"%s\" "
4970 "has terrain hint \"%s\" not in allowed_terrains.",
4972 city_name, p);
4973 ok = FALSE;
4974 } else {
4976 }
4977 } else {
4978 const struct terrain *pterrain = terrain_by_rule_name(p);
4979
4980 if (NULL == pterrain) {
4981 /* Try with removing frequent trailing 's'. */
4982 size_t l = strlen(p);
4983
4984 if (0 < l && 's' == fc_tolower(p[l - 1])) {
4985 char saved = p[l - 1];
4986
4987 p[l - 1] = '\0';
4988 pterrain = terrain_by_rule_name(p);
4989 if (pterrain == NULL) {
4990 /* Didn't help, restore for later allowed_terrains check */
4991 p[l - 1] = saved;
4992 }
4993 }
4994 }
4995
4996 /* Nationset may have been devised with a specific set of terrains
4997 * in mind which don't quite match this ruleset, in which case we
4998 * (a) quietly ignore any hints mentioned that don't happen to be in
4999 * the current ruleset, (b) enforce that terrains mentioned by nations
5000 * must be on the list */
5001 if (pterrain != NULL && game.server.ruledit.allowed_terrains != NULL) {
5002 if (!is_on_allowed_list(p,
5004 /* Terrain exists, but not intended for these nations */
5006 "\"%s\" [%s] %s: city \"%s\" "
5007 "has terrain hint \"%s\" not in allowed_terrains.",
5009 city_name, p);
5010 ok = FALSE;
5011 break;
5012 }
5013 } else if (!pterrain) {
5014 /* Terrain doesn't exist; only complain if it's not on any list */
5016 || !is_on_allowed_list(p,
5019 "\"%s\" [%s] %s: city \"%s\" "
5020 "has unknown terrain hint \"%s\".",
5022 city_name, p);
5023 ok = FALSE;
5024 break;
5025 }
5026 }
5027 if (NULL != pterrain) {
5028 nation_city_set_terrain_preference(pncity, pterrain, prefer);
5029 }
5030 }
5031
5032 p = next ? next + 1 : NULL;
5033 } while (NULL != p && '\0' != *p);
5034 }
5035 }
5036
5037 if (NULL != cities) {
5038 free(cities);
5039 }
5040
5041 return ok;
5042}
5043
5044/**********************************************************************/
5047static bool load_ruleset_nations(struct section_file *file,
5048 struct rscompat_info *compat)
5049{
5050 struct government *gov;
5051 int j;
5052 size_t dim;
5053 char temp_name[MAX_LEN_NAME];
5054 const char **vec;
5055 const char *name, *bad_leader;
5056 const char *sval;
5057 int default_set;
5058 const char *filename = secfile_name(file);
5059 struct section_list *sec = NULL;
5060 enum trait tr;
5061 bool ok = TRUE;
5062
5063 name = secfile_lookup_str_default(file, NULL, "ruledit.nationlist");
5064 if (name != NULL) {
5066 }
5068 "ruledit.embedded_nations");
5069
5070 if (vec != NULL) {
5071 /* Copy to persistent vector */
5074
5075 for (j = 0; j < game.server.ruledit.embedded_nations_count; j++) {
5077 }
5078
5079 free(vec);
5080 }
5081
5083
5084 ruleset_load_traits(game.server.default_traits, file, "default_traits", "");
5085 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5086 if (game.server.default_traits[tr].min < 0) {
5088 }
5089 if (game.server.default_traits[tr].max < 0) {
5091 }
5092 if (game.server.default_traits[tr].fixed < 0) {
5094
5095 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5097 }
5100 "Default values for trait %s not sane.",
5101 trait_name(tr));
5102 ok = FALSE;
5103 break;
5104 }
5105 }
5106
5107 if (ok) {
5109 "compatibility.allowed_govs");
5110 if (vec != NULL) {
5111 /* Copy to persistent vector */
5113 = fc_malloc(game.server.ruledit.ag_count * sizeof(char *));
5115 (const char **)game.server.ruledit.nc_agovs;
5116
5117 for (j = 0; j < game.server.ruledit.ag_count; j++) {
5119 }
5120
5121 free(vec);
5122 }
5123
5125 "compatibility.allowed_terrains");
5126 if (vec != NULL) {
5127 /* Copy to persistent vector */
5129 = fc_malloc(game.server.ruledit.at_count * sizeof(char *));
5131 (const char **)game.server.ruledit.nc_aterrs;
5132
5133 for (j = 0; j < game.server.ruledit.at_count; j++) {
5135 }
5136
5137 free(vec);
5138 }
5139
5141 "compatibility.allowed_styles");
5142 if (vec != NULL) {
5143 /* Copy to persistent vector */
5145 = fc_malloc(game.server.ruledit.as_count * sizeof(char *));
5147 (const char **)game.server.ruledit.nc_astyles;
5148
5149 for (j = 0; j < game.server.ruledit.as_count; j++) {
5151 }
5152
5153 free(vec);
5154 }
5155
5157 "compatibility.default_government");
5158 /* We deliberately don't check this against allowed_govs. It's only
5159 * specified once so not vulnerable to typos, and may usefully be set in
5160 * a specific ruleset to a gov not explicitly known by the nation set. */
5161 if (sval != NULL) {
5163 if (game.default_government == NULL) {
5165 "Tried to set unknown government type \"%s\" as default_government!",
5166 sval);
5167 ok = FALSE;
5168 } else {
5171 }
5172 }
5173 }
5174
5175 if (ok) {
5177 if (sec != NULL) {
5179
5180 section_list_iterate(sec, psection) {
5181 const char *set_name, *set_rule_name, *set_description;
5182
5183 set_name = secfile_lookup_str(file, "%s.name", section_name(psection));
5185 secfile_lookup_str(file, "%s.rule_name", section_name(psection));
5186 set_description = secfile_lookup_str_default(file, "", "%s.description",
5187 section_name(psection));
5188 if (NULL == set_name || NULL == set_rule_name) {
5189 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5190 ok = FALSE;
5191 break;
5192 }
5194 ok = FALSE;
5195 break;
5196 }
5199 sec = NULL;
5200 } else {
5202 "At least one nation set [" NATION_SET_SECTION_PREFIX "_*] "
5203 "must be defined.");
5204 ok = FALSE;
5205 }
5206 }
5207
5208 if (ok) {
5209 /* Default set that every nation is a member of. */
5211 "compatibility.default_nationset");
5212 if (sval != NULL) {
5214 if (pset != NULL) {
5216 } else {
5218 "Unknown default_nationset \"%s\".", sval);
5219 ok = FALSE;
5220 }
5221 } else if (nation_set_count() == 1) {
5222 /* If there's only one set defined, every nation is implicitly a
5223 * member of that set. */
5224 default_set = 0;
5225 } else {
5226 /* No default nation set; every nation must explicitly specify at
5227 * least one set to be a member of. */
5228 default_set = -1;
5229 }
5230 }
5231
5232 if (ok) {
5234 if (sec) {
5235 section_list_iterate(sec, psection) {
5236 struct nation_group *pgroup;
5237 bool hidden;
5238
5239 name = secfile_lookup_str(file, "%s.name", section_name(psection));
5241 if (pgroup == NULL) {
5242 ok = FALSE;
5243 break;
5244 }
5245
5246 hidden = secfile_lookup_bool_default(file, FALSE, "%s.hidden",
5247 section_name(psection));
5249
5250 if (!secfile_lookup_int(file, &j, "%s.match", section_name(psection))) {
5251 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5252 ok = FALSE;
5253 break;
5254 }
5258 sec = NULL;
5259 }
5260 }
5261
5262 if (ok) {
5264 nations_iterate(pnation) {
5265 struct nation_type *pconflict;
5266 const int i = nation_index(pnation);
5267 char tmp[200] = "\0";
5268 const char *barb_type;
5269 const char *sec_name = section_name(section_list_get(sec, i));
5270 const char *legend;
5271
5272 /* Nation sets and groups. */
5273 if (default_set >= 0) {
5274 nation_set_list_append(pnation->sets,
5276 }
5277 vec = secfile_lookup_str_vec(file, &dim, "%s.groups", sec_name);
5278 for (j = 0; j < dim; j++) {
5279 struct nation_set *pset = nation_set_by_rule_name(vec[j]);
5281
5282 fc_assert(pset == NULL || pgroup == NULL);
5283
5284 if (NULL != pset) {
5285 nation_set_list_append(pnation->sets, pset);
5286 } else if (NULL != pgroup) {
5287 nation_group_list_append(pnation->groups, pgroup);
5288 } else {
5289 /* For nation authors, this would probably be considered an error.
5290 * But it can happen normally. The civ1 compatibility ruleset only
5291 * uses the nations that were in civ1, so not all of the links will
5292 * exist. */
5293 log_verbose("Nation %s: Unknown set/group \"%s\".",
5294 nation_rule_name(pnation), vec[j]);
5295 }
5296 }
5297 if (NULL != vec) {
5298 free(vec);
5299 }
5300 if (nation_set_list_size(pnation->sets) < 1) {
5302 "Nation %s is not a member of any nation set",
5303 nation_rule_name(pnation));
5304 ok = FALSE;
5305 break;
5306 }
5307
5308 /* Nation conflicts. */
5309 vec = secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec_name);
5310 for (j = 0; j < dim; j++) {
5312
5313 if (pnation == pconflict) {
5315 "Nation %s conflicts with itself",
5316 nation_rule_name(pnation));
5317 ok = FALSE;
5318 break;
5319 } else if (NULL != pconflict) {
5320 nation_list_append(pnation->server.conflicts_with, pconflict);
5321 } else {
5322 /* For nation authors, this would probably be considered an error.
5323 * But it can happen normally. The civ1 compatibility ruleset only
5324 * uses the nations that were in civ1, so not all of the links will
5325 * exist. */
5326 log_verbose("Nation %s: conflicts_with nation \"%s\" is unknown.",
5327 nation_rule_name(pnation), vec[j]);
5328 }
5329 }
5330 if (NULL != vec) {
5331 free(vec);
5332 }
5333 if (!ok) {
5334 break;
5335 }
5336
5337 /* Nation leaders. */
5338 for (j = 0; j < MAX_NUM_LEADERS; j++) {
5339 const char *sexstr;
5340 sex_t sex;
5341 bool is_male = FALSE;
5342
5343 name = secfile_lookup_str(file, "%s.leaders%d.name", sec_name, j);
5344 if (NULL == name) {
5345 /* No more to read. */
5346 break;
5347 }
5348
5349 if (check_name(name)) {
5350 /* The ruleset contains a name that is too long. This shouldn't
5351 * happen - if it does, the author should get immediate feedback */
5354 "Nation %s: leader name \"%s\" is too long.",
5355 nation_rule_name(pnation), name);
5356 ok = FALSE;
5357 break;
5358 }
5359
5360 sexstr = secfile_lookup_str(file, "%s.leaders%d.sex", sec_name, j);
5361 if (NULL == sexstr) {
5363 "Nation %s: leader \"%s\": %s.",
5364 nation_rule_name(pnation), name, secfile_error());
5365 ok = FALSE;
5366 break;
5367 }
5368
5370
5371 switch (sex) {
5372 case SEX_MALE:
5373 is_male = TRUE;
5374 break;
5375 case SEX_FEMALE:
5376 is_male = FALSE;
5377 break;
5378 case SEX_UNKNOWN:
5380 "Nation %s: leader \"%s\" has unsupported "
5381 "sex variant \"%s\".",
5382 nation_rule_name(pnation), name, sexstr);
5383 ok = FALSE;
5384 break;
5385 }
5386
5387 if (ok) {
5388 (void) nation_leader_new(pnation, name, is_male);
5389 }
5390 }
5391 if (!ok) {
5392 break;
5393 }
5394
5395 /* Check the number of leaders. */
5396 if (MAX_NUM_LEADERS == j) {
5397 /* Too much leaders, get the real number defined in the ruleset. */
5398 while (NULL != secfile_entry_lookup(file, "%s.leaders%d.name",
5399 sec_name, j)) {
5400 j++;
5401 }
5403 "Nation %s: Too many leaders; max is %d",
5405 ok = FALSE;
5406 break;
5407 } else if (0 == j) {
5409 "Nation %s: no leaders; at least one is required.",
5410 nation_rule_name(pnation));
5411 ok = FALSE;
5412 break;
5413 }
5414
5415 /* Check if leader name is not already defined in this nation. */
5416 if ((bad_leader = check_leader_names(pnation))) {
5418 "Nation %s: leader \"%s\" defined more than once.",
5419 nation_rule_name(pnation), bad_leader);
5420 ok = FALSE;
5421 break;
5422 }
5423
5424 /* Nation player color preference, if any */
5425 fc_assert_ret_val(pnation->server.rgb == NULL, FALSE);
5426 (void) rgbcolor_load(file, &pnation->server.rgb, "%s.color", sec_name);
5427
5428 /* Load nation traits */
5429 ruleset_load_traits(pnation->server.traits, file, sec_name, "trait_");
5430 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5431 bool server_traits_used = TRUE;
5432
5433 if (pnation->server.traits[tr].min < 0) {
5434 pnation->server.traits[tr].min = game.server.default_traits[tr].min;
5435 } else {
5437 }
5438 if (pnation->server.traits[tr].max < 0) {
5439 pnation->server.traits[tr].max = game.server.default_traits[tr].max;
5440 } else {
5442 }
5443 if (pnation->server.traits[tr].fixed < 0) {
5444 if (server_traits_used) {
5445 pnation->server.traits[tr].fixed = game.server.default_traits[tr].fixed;
5446 } else {
5447 int diff = pnation->server.traits[tr].max - pnation->server.traits[tr].min;
5448
5449 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5450 pnation->server.traits[tr].fixed = diff / 2 + pnation->server.traits[tr].min;
5451 }
5452 }
5453 if (pnation->server.traits[tr].max < pnation->server.traits[tr].min) {
5455 "%s values for trait %s not sane.",
5456 nation_rule_name(pnation), trait_name(tr));
5457 ok = FALSE;
5458 break;
5459 }
5460 }
5461
5462 if (!ok) {
5463 break;
5464 }
5465
5466 pnation->is_playable =
5467 secfile_lookup_bool_default(file, TRUE, "%s.is_playable", sec_name);
5468
5469 /* Check barbarian type. Default is "None" meaning not a barbarian */
5470 barb_type = secfile_lookup_str_default(file, "None",
5471 "%s.barbarian_type", sec_name);
5472 pnation->barb_type = barbarian_type_by_name(barb_type, fc_strcasecmp);
5473 if (!barbarian_type_is_valid(pnation->barb_type)) {
5475 "Nation %s, barbarian_type is invalid (\"%s\")",
5476 nation_rule_name(pnation), barb_type);
5477 ok = FALSE;
5478 break;
5479 }
5480
5481 if (pnation->barb_type != NOT_A_BARBARIAN
5482 && pnation->is_playable) {
5483 /* We can't allow players to use barbarian nations, barbarians
5484 * may run out of nations */
5486 "Nation %s marked both barbarian and playable.",
5487 nation_rule_name(pnation));
5488 ok = FALSE;
5489 break;
5490 }
5491
5492 /* Flags */
5493 sz_strlcpy(pnation->flag_graphic_str,
5494 secfile_lookup_str_default(file, "-", "%s.flag", sec_name));
5495 sz_strlcpy(pnation->flag_graphic_alt,
5497 "%s.flag_alt", sec_name));
5498
5499 /* Ruler titles */
5500 for (j = 0;; j++) {
5501 const char *male, *female;
5502
5504 "%s.ruler_titles%d.government",
5505 sec_name, j);
5506 if (NULL == name) {
5507 /* End of the list of ruler titles. */
5508 break;
5509 }
5510
5511 /* NB: even if the government doesn't exist, we load the entries for
5512 * the ruler titles to avoid warnings about unused entries. */
5513 male = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
5514 sec_name, j);
5515 female = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
5516 sec_name, j);
5518
5519 /* Nationset may have been devised with a specific set of govs in
5520 * mind which don't quite match this ruleset, in which case we
5521 * (a) quietly ignore any govs mentioned that don't happen to be in
5522 * the current ruleset, (b) enforce that govs mentioned by nations
5523 * must be on the list */
5524 if (gov != NULL && game.server.ruledit.allowed_govs != NULL) {
5528 /* Gov exists, but not intended for these nations */
5529 gov = NULL;
5531 "Nation %s: government \"%s\" not in allowed_govs.",
5532 nation_rule_name(pnation), name);
5533 ok = FALSE;
5534 break;
5535 }
5536 } else if (!gov) {
5537 /* Gov doesn't exist; only complain if it's not on any list */
5543 "Nation %s: government \"%s\" not found.",
5544 nation_rule_name(pnation), name);
5545 ok = FALSE;
5546 break;
5547 }
5548 }
5549 if (NULL != male && NULL != female) {
5550 if (gov) {
5551 (void) government_ruler_title_new(gov, pnation, male, female);
5552 }
5553 } else {
5555 ok = FALSE;
5556 break;
5557 }
5558 }
5559 if (!ok) {
5560 break;
5561 }
5562
5563 /* City styles */
5564 name = secfile_lookup_str(file, "%s.style", sec_name);
5565 if (!name) {
5567 ok = FALSE;
5568 break;
5569 }
5570 pnation->style = style_by_rule_name(name);
5571 if (pnation->style == NULL) {
5577 "Nation %s: Illegal style \"%s\"",
5578 nation_rule_name(pnation), name);
5579 ok = FALSE;
5580 break;
5581 } else {
5582 log_verbose("Nation %s: style \"%s\" not supported in this "
5583 "ruleset; using default.",
5584 nation_rule_name(pnation), name);
5585 pnation->style = style_by_number(0);
5586 }
5587 }
5588
5589 /* Civilwar nations */
5590 vec = secfile_lookup_str_vec(file, &dim,
5591 "%s.civilwar_nations", sec_name);
5592 for (j = 0; j < dim; j++) {
5594
5595 /* No test for duplicate nations is performed. If there is a duplicate
5596 * entry it will just cause that nation to have an increased
5597 * probability of being chosen. */
5598 if (pconflict == pnation) {
5600 "Nation %s is its own civil war nation",
5601 nation_rule_name(pnation));
5602 ok = FALSE;
5603 break;
5604 } else if (NULL != pconflict) {
5605 nation_list_append(pnation->server.civilwar_nations, pconflict);
5606 nation_list_append(pconflict->server.parent_nations, pnation);
5607 } else {
5608 /* For nation authors, this would probably be considered an error.
5609 * But it can happen normally. The civ1 compatibility ruleset only
5610 * uses the nations that were in civ1, so not all of the links will
5611 * exist. */
5612 log_verbose("Nation %s: civil war nation \"%s\" is unknown.",
5613 nation_rule_name(pnation), vec[j]);
5614 }
5615 }
5616 if (NULL != vec) {
5617 free(vec);
5618 }
5619 if (!ok) {
5620 break;
5621 }
5622
5623 /* Load nation specific initial items */
5624 if (!lookup_tech_list(file, sec_name, "init_techs",
5625 pnation->init_techs, filename)) {
5626 ok = FALSE;
5627 break;
5628 }
5629 if (!lookup_building_list(file, sec_name, "init_buildings",
5630 pnation->init_buildings, filename)) {
5631 ok = FALSE;
5632 break;
5633 }
5634 if (!lookup_unit_list(file, sec_name, "init_units",
5635 pnation->init_units, filename)) {
5636 ok = FALSE;
5637 break;
5638 }
5639 fc_strlcat(tmp, sec_name, 200);
5640 fc_strlcat(tmp, ".init_government", 200);
5641 if (secfile_entry_by_path(file, tmp)) {
5642 pnation->init_government = lookup_government(file, tmp, filename,
5643 NULL);
5644 /* If specified, init_government has to be in this specific ruleset,
5645 * not just allowed_govs */
5646 if (pnation->init_government == NULL) {
5647 ok = FALSE;
5648 break;
5649 }
5650 /* ...but if a list of govs has been specified, enforce that this
5651 * nation's init_government is on the list. */
5653 && !is_on_allowed_list(government_rule_name(pnation->init_government),
5657 "Nation %s: init_government \"%s\" not allowed.",
5658 nation_rule_name(pnation),
5659 government_rule_name(pnation->init_government));
5660 ok = FALSE;
5661 break;
5662 }
5663 }
5664
5665 /* Read default city names. */
5666 if (!load_city_name_list(file, pnation, sec_name, "cities",
5669 ok = FALSE;
5670 break;
5671 }
5672
5673 legend = secfile_lookup_str_default(file, "", "%s.legend", sec_name);
5674 pnation->legend = fc_strdup(legend);
5675 if (check_strlen(pnation->legend, MAX_LEN_MSG, NULL)) {
5677 "Nation %s: legend \"%s\" is too long.",
5678 nation_rule_name(pnation),
5679 pnation->legend);
5680 ok = FALSE;
5681 break;
5682 }
5683
5684 pnation->player = NULL;
5687 sec = NULL;
5688 }
5689
5690 /* Clean up on aborted load */
5691 if (sec != NULL) {
5692 fc_assert(!ok);
5694 }
5695
5696 if (ok) {
5698 }
5699
5700 if (ok) {
5701 /* Update cached number of playable nations in the current set */
5703
5704 /* Sanity checks on all sets */
5707
5708 nations_iterate(pnation) {
5709 if (nation_is_in_set(pnation, pset)) {
5710 switch (nation_barbarian_type(pnation)) {
5711 case NOT_A_BARBARIAN:
5712 if (is_nation_playable(pnation)) {
5713 num_playable++;
5714 }
5715 break;
5716 case LAND_BARBARIAN:
5718 break;
5719 case SEA_BARBARIAN:
5721 break;
5722 case ANIMAL_BARBARIAN:
5723 /* Animals are optional */
5724 break;
5727 break;
5728 default:
5730 }
5731 }
5733 if (num_playable < 1) {
5735 "Nation set \"%s\" has no playable nations. "
5736 "At least one required!", nation_set_rule_name(pset));
5737 ok = FALSE;
5738 break;
5739 }
5740 if (barb_land_count == 0 && barb_both_count == 0) {
5742 "No land barbarian nation defined in set \"%s\". "
5743 "At least one required!", nation_set_rule_name(pset));
5744 ok = FALSE;
5745 break;
5746 }
5747 if (barb_sea_count == 0 && barb_both_count == 0) {
5749 "No sea barbarian nation defined in set \"%s\". "
5750 "At least one required!", nation_set_rule_name(pset));
5751 ok = FALSE;
5752 break;
5753 }
5755 }
5756
5757 return ok;
5758}
5759
5760/**********************************************************************/
5764static bool load_style_names(struct section_file *file,
5765 struct rscompat_info *compat)
5766{
5767 bool ok = TRUE;
5768 struct section_list *sec;
5769 const char *filename = secfile_name(file);
5770
5771 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5772 return FALSE;
5773 }
5774
5775 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5776 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5777
5779 if (NULL == sec) {
5781 "No available nation styles in this ruleset!");
5782 ok = FALSE;
5783 } else {
5785
5787
5789 const int i = style_index(ps);
5790 const char *sec_name = section_name(section_list_get(sec, i));
5791
5792 ruleset_load_names(&ps->name, NULL, file, sec_name);
5794 }
5795
5797
5798 if (ok) {
5799 /* The citystyle sections: */
5800 int i = 0;
5801
5803 if (NULL != sec) {
5805 section_list_iterate(sec, style) {
5806 if (!ruleset_load_names(&city_styles[i].name, NULL, file, section_name(style))) {
5807 ok = FALSE;
5808 break;
5809 }
5810 i++;
5812
5814 } else {
5816 }
5817 }
5818
5819 return ok;
5820}
5821
5822/**********************************************************************/
5825static bool load_ruleset_styles(struct section_file *file,
5826 struct rscompat_info *compat)
5827{
5828 struct section_list *sec;
5829 int i;
5830 bool ok = TRUE;
5831
5832 /* City Styles ... */
5833
5835
5836 /* Get rest: */
5837 for (i = 0; i < game.control.num_city_styles; i++) {
5838 struct requirement_vector *reqs;
5839 const char *sec_name = section_name(section_list_get(sec, i));
5840
5841 sz_strlcpy(city_styles[i].graphic,
5842 secfile_lookup_str(file, "%s.graphic", sec_name));
5843 sz_strlcpy(city_styles[i].graphic_alt,
5844 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
5845 sz_strlcpy(city_styles[i].citizens_graphic,
5847 "%s.citizens_graphic", sec_name));
5848
5850 if (reqs == NULL) {
5851 ok = FALSE;
5852 break;
5853 }
5855 }
5856
5858
5859 if (ok) {
5861
5862 if (sec != NULL) {
5863 int musi;
5864
5867 musi = 0;
5868
5869 section_list_iterate(sec, psection) {
5870 struct requirement_vector *reqs;
5872 const char *sec_name = section_name(psection);
5873
5874 sz_strlcpy(pmus->music_peaceful,
5876 "%s.music_peaceful", sec_name));
5877 sz_strlcpy(pmus->music_combat,
5879 "%s.music_combat", sec_name));
5880
5881 reqs = lookup_req_list(file, compat, sec_name, "reqs", "Music Style");
5882 if (reqs == NULL) {
5883 ok = FALSE;
5884 break;
5885 }
5887
5888 musi++;
5890 }
5891
5893 }
5894
5895 return ok;
5896}
5897
5898/**********************************************************************/
5905 const char *uflags_path,
5906 const char *filename)
5907{
5908 /* Add each listed protected unit type flag as a !present
5909 * requirement. */
5910 if (secfile_entry_lookup(file, "%s", uflags_path)) {
5912 size_t psize;
5913 int i;
5914
5917 "%s", uflags_path);
5918
5919 if (!protecor_flag) {
5920 /* Entity exists but couldn't read it. */
5922 "\"%s\": %s: bad unit type flag list.",
5923 filename, uflags_path);
5924
5925 return FALSE;
5926 }
5927
5928 for (i = 0; i < psize; i++) {
5932 FALSE, FALSE, TRUE,
5933 protecor_flag[i]));
5934 }
5935
5937 }
5938
5939 return TRUE;
5940}
5941
5942/**********************************************************************/
5948 const char *actions_path,
5949 const char *filename)
5950{
5951 /* Read the alternative actions. */
5952 if (secfile_entry_lookup(file, "%s", actions_path)) {
5953 enum gen_action *unit_acts;
5954 size_t asize;
5955 int i;
5956
5958 "%s", actions_path);
5959
5960 if (!unit_acts) {
5961 /* Entity exists but couldn't read it. */
5963 "\"%s\": %s: bad action list",
5964 filename, actions_path);
5965
5966 return FALSE;
5967 }
5968
5969 for (i = 0; i < asize; i++) {
5970 auto_perf->alternatives[i] = unit_acts[i];
5971 }
5972
5973 free(unit_acts);
5974 }
5975
5976 return TRUE;
5977}
5978
5979/**********************************************************************/
5984 const char *item,
5985 const char *filename)
5986{
5987 char uflags_path[100];
5988 char action_path[100];
5989
5991 "missing_unit_upkeep.%s_protected", item);
5993 "missing_unit_upkeep.%s_unit_act", item);
5994
5996 filename)
5998 filename));
5999}
6000
6001/**********************************************************************/
6004static bool load_ruleset_cities(struct section_file *file,
6005 struct rscompat_info *compat)
6006{
6007 const char *filename = secfile_name(file);
6008 const char *item;
6009 struct section_list *sec;
6010 bool ok = TRUE;
6011
6012 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6013 return FALSE;
6014 }
6015
6016 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6017 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6018
6019 /* Specialist options */
6021 if (!sec) {
6022 ruleset_error(NULL, LOG_ERROR, "\"%s\": No specialists.", filename);
6023 ok = FALSE;
6024 } else if (section_list_size(sec) >= SP_MAX) {
6026 "\"%s\": Too many specialists (%d, max %d).",
6027 filename, section_list_size(sec), SP_MAX);
6028 ok = FALSE;
6029 }
6030
6031 if (ok) {
6032 int i = 0;
6033 const char *tag;
6034
6036
6037 section_list_iterate(sec, psection) {
6038 struct specialist *s = specialist_by_number(i);
6039 struct requirement_vector *reqs;
6040 const char *sec_name = section_name(psection);
6041
6042 if (!ruleset_load_names(&s->name, NULL, file, sec_name)) {
6043 ok = FALSE;
6044 break;
6045 }
6046
6048 "%s.short_name", sec_name);
6050
6051 tag = secfile_lookup_str(file, "%s.graphic", sec_name);
6052 if (tag == NULL) {
6054 "\"%s\": No graphic tag for specialist at %s.",
6055 filename, sec_name);
6056 ok = FALSE;
6057 break;
6058 }
6059 sz_strlcpy(s->graphic_str, tag);
6062 "%s.graphic_alt", sec_name));
6063
6065 if (reqs == NULL) {
6066 ok = FALSE;
6067 break;
6068 }
6070
6071 s->helptext = lookup_strvec(file, sec_name, "helptext");
6072
6073 if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
6075 }
6076 i++;
6078 }
6079
6080 if (ok && DEFAULT_SPECIALIST == -1) {
6082 "\"%s\": must have zero reqs for at least one "
6083 "specialist type.", filename);
6084 ok = FALSE;
6085 }
6087 sec = NULL;
6088
6089 if (ok) {
6090 /* City Parameters */
6091
6094 "parameters.celebrate_size_limit");
6096 secfile_lookup_int_default(file, GAME_DEFAULT_ADDTOSIZE, "parameters.add_to_size_limit");
6099 "parameters.angry_citizens");
6100
6102 secfile_lookup_bool_default(file, GAME_DEFAULT_CHANGABLE_TAX, "parameters.changable_tax");
6104 secfile_lookup_int_default(file, 0, "parameters.forced_science");
6106 secfile_lookup_int_default(file, 100, "parameters.forced_luxury");
6108 secfile_lookup_int_default(file, 0, "parameters.forced_gold");
6110 + game.info.forced_gold != 100) {
6112 "\"%s\": Forced taxes do not add up in ruleset!",
6113 filename);
6114 ok = FALSE;
6115 }
6116 }
6117
6118 if (ok) {
6120
6121 /* civ1 & 2 didn't reveal tiles */
6124 "parameters.vision_reveal_tiles");
6125
6127 secfile_lookup_int_default(file, 1, "parameters.pop_report_zeroes");
6128
6129 /* Citizens configuration. */
6132 "citizen.nationality");
6133
6134 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
6135 /* Same as old hardcoded behavior */
6137 }
6140 "citizen.ubuilder_nationality");
6143 "citizen.convert_speed");
6145 secfile_lookup_int_default(file, 0, "citizen.partisans_pct");
6147 secfile_lookup_int_default(file, 0, "citizen.conquest_convert_pct");
6148 }
6149
6150 if (ok) {
6151 /* Missing unit upkeep. */
6153
6154 /* Can't pay food upkeep! */
6156 auto_perf->cause = AAPC_UNIT_UPKEEP;
6157
6158 /* This is about food upkeep. */
6160 req_from_str("OutputType", "Local",
6161 FALSE, TRUE, TRUE,
6162 "Food"));
6163
6164 /* Internally represented as an action auto performer rule. */
6165 if (!load_muuk_as_action_auto(file, auto_perf, "food", filename)) {
6166 ok = FALSE;
6167 }
6168
6171 "missing_unit_upkeep.food_wipe");
6172
6173 /* Can't pay gold upkeep! */
6175 auto_perf->cause = AAPC_UNIT_UPKEEP;
6176
6177 /* This is about gold upkeep. */
6179 req_from_str("OutputType", "Local",
6180 FALSE, TRUE, TRUE,
6181 "Gold"));
6182
6183 /* Internally represented as an action auto performer rule. */
6184 if (!load_muuk_as_action_auto(file, auto_perf, "gold", filename)) {
6185 ok = FALSE;
6186 }
6187
6190 "missing_unit_upkeep.gold_wipe");
6191
6192 /* Can't pay shield upkeep! */
6194 auto_perf->cause = AAPC_UNIT_UPKEEP;
6195
6196 /* This is about shield upkeep. */
6198 req_from_str("OutputType", "Local",
6199 FALSE, TRUE, TRUE,
6200 "Shield"));
6201
6202 /* Internally represented as an action auto performer rule. */
6203 if (!load_muuk_as_action_auto(file, auto_perf, "shield", filename)) {
6204 ok = FALSE;
6205 }
6206
6209 "missing_unit_upkeep.shield_wipe");
6210 }
6211
6212 if (ok) {
6214 }
6215
6216 return ok;
6217}
6218
6219/**********************************************************************/
6222static bool load_ruleset_effects(struct section_file *file,
6223 struct rscompat_info *compat)
6224{
6225 struct section_list *sec;
6226 const char *filename;
6227 bool ok = TRUE;
6228
6229 filename = secfile_name(file);
6230
6231 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6232 return FALSE;
6233 }
6234
6235 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6236 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6237
6239
6240 if (sec != NULL) {
6241 section_list_iterate(sec, psection) {
6242 const char *sec_name = section_name(psection);
6243 enum effect_type main_type;
6244 enum effect_type ai_valued_as;
6245 const char *type;
6246
6247 type = secfile_lookup_str(file, "%s.type", sec_name);
6248 if (type == NULL) {
6250 "\"%s\" [%s] missing effect type.",
6251 filename, sec_name);
6252 ok = FALSE;
6253 break;
6254 }
6258 "\"%s\" [%s] lists unknown effect type \"%s\".",
6259 filename, sec_name, type);
6260 ok = FALSE;
6261 break;
6262 }
6263 if (!is_user_effect(main_type)) {
6265 "\"%s\" [%s] type \"%s\" is not an user effect.",
6266 filename, sec_name, type);
6267 ok = FALSE;
6268 break;
6269 }
6270
6271 type = secfile_lookup_str(file, "%s.ai_valued_as", sec_name);
6272 if (type == NULL) {
6274 "\"%s\" [%s] missing ai_valued_as.",
6275 filename, sec_name);
6276 ok = FALSE;
6277 break;
6278 }
6282 "\"%s\" [%s] lists unknown ai_valued_as \"%s\".",
6283 filename, sec_name, type);
6284 ok = FALSE;
6285 break;
6286 }
6289 "\"%s\" [%s] ai_valued_as \"%s\" is an user effect.",
6290 filename, sec_name, type);
6291 ok = FALSE;
6292 break;
6293 }
6294
6296 /* It has been set already! */
6298 "\"%s\" [%s] Duplicate \"%s\" entry.",
6299 filename, sec_name, type);
6300 ok = FALSE;
6301 break;
6302 }
6303
6306
6308 }
6309
6310 /* Parse effects and add them to the effects ruleset cache. */
6312 section_list_iterate(sec, psection) {
6313 enum effect_type eff;
6314 int value;
6315 struct multiplier *pmul;
6316 struct effect *peffect;
6317 const char *sec_name = section_name(psection);
6318 struct requirement_vector *reqs;
6319 const char *type;
6320 const char *comment;
6321
6322 type = secfile_lookup_str(file, "%s.type", sec_name);
6323
6324 if (type == NULL) {
6326 "\"%s\" [%s] missing effect type.",
6327 filename, sec_name);
6328 ok = FALSE;
6329 break;
6330 }
6331
6333 if (!effect_type_is_valid(eff)) {
6335 "\"%s\" [%s] lists unknown effect type \"%s\".",
6336 filename, sec_name, type);
6337 ok = FALSE;
6338 break;
6339 }
6340
6341 value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
6342
6343 {
6344 const char *multiplier_name
6345 = secfile_lookup_str(file, "%s.multiplier", sec_name);
6346
6347 if (multiplier_name) {
6349 if (!pmul) {
6351 "\"%s\" [%s] has unknown multiplier \"%s\".",
6352 filename, sec_name, multiplier_name);
6353 ok = FALSE;
6354 break;
6355 }
6356 } else {
6357 pmul = NULL;
6358 }
6359 }
6360
6361 peffect = effect_new(eff, value, pmul);
6362
6363 reqs = lookup_req_list(file, compat, sec_name, "reqs", type);
6364 if (reqs == NULL) {
6365 ok = FALSE;
6366 break;
6367 }
6368
6372
6373 comment = secfile_lookup_str_default(file, NULL, "%s.comment", sec_name);
6374
6375 if (comment != NULL) {
6376 peffect->rulesave.comment = fc_strdup(comment);
6377 }
6378
6381
6382 if (ok) {
6384 }
6385
6386 return ok;
6387}
6388
6389/**********************************************************************/
6393 int def, int min, int max,
6394 const char *path, ...)
6395{
6396 char fullpath[256];
6397 int ival;
6398 va_list args;
6399
6400 va_start(args, path);
6401 fc_vsnprintf(fullpath, sizeof(fullpath), path, args);
6402 va_end(args);
6403
6404 if (!secfile_lookup_int(file, &ival, "%s", fullpath)) {
6405 ival = def;
6406 }
6407
6408 if (ival < min) {
6410 "\"%s\" should be in the interval [%d, %d] "
6411 "but is %d; using the minimal value.",
6412 fullpath, min, max, ival);
6413 ival = min;
6414 }
6415
6416 if (ival > max) {
6418 "\"%s\" should be in the interval [%d, %d] "
6419 "but is %d; using the maximal value.",
6420 fullpath, min, max, ival);
6421 ival = max;
6422 }
6423
6424 return ival;
6425}
6426
6427/**********************************************************************/
6430static bool load_action_ui_name(struct section_file *file, int act,
6431 const char *entry_name,
6432 const char *compat_name)
6433{
6434 const char *text;
6435 const char *def = action_ui_name_default(act);
6436
6437 if (compat_name != NULL) {
6438 def = secfile_lookup_str_default(file, def,
6439 "actions.%s", compat_name);
6440 }
6441
6442 text = secfile_lookup_str_default(file, def,
6443 "actions.%s", entry_name);
6444 sz_strlcpy(action_by_number(act)->ui_name, text);
6445
6446 return TRUE;
6447}
6448
6449/**********************************************************************/
6452static bool load_action_range_max(struct section_file *file, action_id act)
6453{
6454 struct action *paction = action_by_number(act);
6455 const char *vname = action_max_range_ruleset_var_name(act);
6456
6457 if (vname != NULL) {
6458 struct entry *pentry;
6459 int max_range;
6460
6461 pentry = secfile_entry_lookup(file, "actions.%s", vname);
6462
6463 if (pentry == NULL) {
6465 } else {
6466 const char *custom;
6467
6470 /* max_range already assigned */
6471 } else if (entry_type_get(pentry) == ENTRY_STR
6475 } else {
6476 ruleset_error(NULL, LOG_ERROR, "Bad actions.%s",
6479
6480 return FALSE;
6481 }
6482 }
6483
6485 }
6486
6487 return TRUE;
6488}
6489
6490/**********************************************************************/
6493static bool load_action_range(struct section_file *file, action_id act)
6494{
6495 struct action *paction = action_by_number(act);
6496 const char *vname;
6497
6498 if (!load_action_range_max(file, act)) {
6499 return FALSE;
6500 }
6501
6503 if (vname != NULL) {
6504 /* Min range can be loaded from the ruleset. */
6508 "actions.%s",
6509 vname);
6510 }
6511
6512 return TRUE;
6513}
6514
6515/**********************************************************************/
6518static bool load_action_kind(struct section_file *file, action_id act)
6519{
6520 struct action *paction = action_by_number(act);
6522
6523 if (var_name != NULL) {
6527 paction->result),
6529 "actions.%s", var_name);
6530 } else {
6533 }
6534
6535 return TRUE;
6536}
6537
6538/**********************************************************************/
6542 action_id act)
6543{
6545 /* Actor consumption can be loaded from the ruleset. */
6548 file, RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS, "actions.%s",
6550 }
6551
6552 return TRUE;
6553}
6554
6555/**********************************************************************/
6559 const char *filename,
6560 struct action *paction)
6561{
6563 /* Action blocking can be loaded from the ruleset. */
6564
6565 char fullpath[1024];
6566
6567 fc_snprintf(fullpath, sizeof(fullpath), "actions.%s",
6569
6570 if (secfile_entry_by_path(file, fullpath)) {
6572 size_t asize;
6573 int j;
6574
6577
6578 if (!blocking_actions) {
6579 /* Entity exists but couldn't read it. */
6581 "\"%s\": %s: bad action list",
6582 filename, fullpath);
6583
6584 return FALSE;
6585 }
6586
6587 for (j = 0; j < asize; j++) {
6588 BV_SET(paction->blocked_by, blocking_actions[j]);
6589 }
6590
6592 }
6593 }
6594
6595 return TRUE;
6596}
6597
6598/**********************************************************************/
6603 const char *filename,
6604 int performer_slot,
6605 struct action *paction)
6606{
6608 char action_list_path[100];
6609
6611 /* Not relevant. */
6612 return TRUE;
6613 }
6614
6616 auto_perf->cause = AAPC_POST_ACTION;
6617
6618 /* Limit auto performer to this action. */
6621 FALSE, TRUE, TRUE,
6622 paction->id));
6623
6624 /* Load the list of actions. */
6626 "actions.%s",
6629 action_list_path, filename)) {
6630 return FALSE;
6631 }
6632
6633 return TRUE;
6634}
6635
6636/**********************************************************************/
6639static bool lookup_bv_actions(struct section_file *file,
6640 const char *filename,
6641 bv_actions *target,
6642 const char *path)
6643{
6644 if (secfile_entry_by_path(file, path)) {
6646 size_t asize;
6647 int j;
6648
6650 "%s", path);
6651
6652 if (!listed_actions) {
6653 /* Entity exists but couldn't read it. */
6654 ruleset_error(NULL, LOG_ERROR, "\"%s\": %s: bad action list",
6655 filename, path);
6656
6657 return FALSE;
6658 }
6659
6660 for (j = 0; j < asize; j++) {
6661 BV_SET(*target, listed_actions[j]);
6662 }
6663
6665 }
6666
6667 return TRUE;
6668}
6669
6670/**********************************************************************/
6673static bool load_ruleset_game(struct section_file *file, bool act,
6674 struct rscompat_info *compat)
6675{
6676 const char *sval, **svec;
6677 const char *filename;
6678 int *food_ini;
6679 int i;
6680 size_t teams;
6681 const char *pref_text;
6682 size_t gni_tmp;
6683 struct section_list *sec;
6684 size_t nval;
6685 const char *name;
6686 bool ok = TRUE;
6687
6688 if (file == NULL) {
6689 return FALSE;
6690 }
6691 filename = secfile_name(file);
6692
6693 name = secfile_lookup_str_default(file, NULL, "ruledit.description_file");
6694 if (name != NULL) {
6696 }
6697
6698 /* Section: tileset */
6699 pref_text = secfile_lookup_str_default(file, "", "tileset.prefered");
6700 if (pref_text[0] != '\0') {
6701 log_deprecation("Entry tileset.prefered in game.ruleset."
6702 " Use correct spelling tileset.preferred instead");
6703 }
6704 pref_text = secfile_lookup_str_default(file, pref_text, "tileset.preferred");
6705 if (pref_text[0] != '\0') {
6706 /* There was tileset suggestion */
6708 } else {
6709 /* No tileset suggestions */
6710 game.control.preferred_tileset[0] = '\0';
6711 }
6712
6713 /* Section: soundset */
6714 pref_text = secfile_lookup_str_default(file, "", "soundset.prefered");
6715 if (pref_text[0] != '\0') {
6716 log_deprecation("Entry soundset.prefered in game.ruleset."
6717 " Use correct spelling soundset.preferred instead");
6718 }
6719 pref_text = secfile_lookup_str_default(file, pref_text, "soundset.preferred");
6720 if (pref_text[0] != '\0') {
6721 /* There was soundset suggestion */
6723 } else {
6724 /* No soundset suggestions */
6726 }
6727
6728 /* Section: musicset */
6729 pref_text = secfile_lookup_str_default(file, "", "musicset.prefered");
6730 if (pref_text[0] != '\0') {
6731 log_deprecation("Entry musicset.prefered in game.ruleset."
6732 " Use correct spelling musicset.preferred instead");
6733 }
6734 pref_text = secfile_lookup_str_default(file, pref_text, "musicset.preferred");
6735 if (pref_text[0] != '\0') {
6736 /* There was musicset suggestion */
6738 } else {
6739 /* No musicset suggestions */
6741 }
6742
6743 /* Section: about */
6744 pref_text = secfile_lookup_str(file, "about.name");
6745 /* Ruleset/modpack name found */
6747
6748 pref_text = secfile_lookup_str_default(file, "", "about.version");
6749 if (pref_text[0] != '\0') {
6750 /* Ruleset/modpack version found */
6752 } else {
6753 /* No version information */
6754 game.control.version[0] = '\0';
6755 }
6756
6757 pref_text = secfile_lookup_str_default(file, "", "about.alt_dir");
6758 if (pref_text[0] != '\0') {
6759 /* Alt directory definition found. */
6761 } else {
6762 /* No alt directory information */
6763 game.control.alt_dir[0] = '\0';
6764 }
6765
6766 pref_text = secfile_lookup_str_default(file, "", "about.summary");
6767 if (pref_text[0] != '\0') {
6768 int len;
6769
6770 /* Ruleset/modpack summary found */
6771 len = strlen(pref_text);
6774 } else {
6775 /* No summary */
6776 if (game.ruleset_summary != NULL) {
6779 }
6780 }
6781
6782 pref_text = secfile_lookup_str_default(file, "", "about.description");
6783 if (pref_text[0] != '\0') {
6784 int len;
6785
6786 /* Ruleset/modpack description found */
6787 len = strlen(pref_text);
6791 } else {
6792 /* No description */
6793 if (game.ruleset_description != NULL) {
6796 }
6798 }
6799
6800 pref_text = secfile_lookup_str_default(file, "", "about.capabilities");
6801 if (pref_text[0] != '\0') {
6802 int len = strlen(pref_text);
6803
6806 } else {
6808 game.ruleset_capabilities[0] = '\0';
6809 }
6810
6811 /* Section: options */
6812 if (!lookup_tech_list(file, "options", "global_init_techs",
6813 game.rgame.global_init_techs, filename)) {
6814 ok = FALSE;
6815 }
6816
6817 if (ok) {
6818 if (!lookup_building_list(file, "options", "global_init_buildings",
6819 game.rgame.global_init_buildings, filename)) {
6820 ok = FALSE;
6821 }
6822 }
6823
6824 if (ok) {
6825 const char **slist;
6826 int j;
6827
6829 "options.popup_tech_help");
6830
6831 /* section: civstyle */
6834 "civstyle.base_pollution");
6835
6837
6838 slist = secfile_lookup_str_vec(file, &nval, "civstyle.gameloss_style");
6839 for (j = 0; j < nval; j++) {
6840 enum gameloss_style style;
6841
6842 sval = slist[j];
6843 if (strcmp(sval, "") == 0) {
6844 continue;
6845 }
6847 if (!gameloss_style_is_valid(style)) {
6849 "\"%s\": bad value \"%s\" for gameloss_style.",
6850 filename, sval);
6851 ok = FALSE;
6852 break;
6853 } else {
6854 game.info.gameloss_style |= style;
6855 }
6856 }
6857 free(slist);
6858 }
6859
6860 if (ok) {
6866 "civstyle.happy_cost");
6872 "civstyle.food_cost");
6874 = secfile_lookup_bool_default(file, TRUE, "civstyle.civil_war_enabled");
6875
6878 "civstyle.civil_war_bonus_celebrating");
6879
6882 "civstyle.civil_war_bonus_unhappy");
6883
6889 "civstyle.base_bribe_cost");
6895 "civstyle.ransom_gold");
6898 "civstyle.pillage_select");
6899
6902 "civstyle.tech_steal_allow_holes");
6905 "civstyle.tech_trade_allow_holes");
6908 "civstyle.tech_trade_loss_allow_holes");
6911 "civstyle.tech_parasite_allow_holes");
6914 "civstyle.tech_loss_allow_holes");
6915
6921 "civstyle.upgrade_veteran_loss");
6927 "civstyle.autoupgrade_veteran_loss");
6928
6934 "research.base_tech_cost");
6935
6936 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
6937 /* base_tech_cost used to be used for this too. */
6943 "research.min_tech_cost");
6944 } else {
6950 "research.min_tech_cost");
6951 }
6952
6954 "civstyle.granary_food_ini");
6956
6959 "Too many granary_food_ini entries (%d, max %d)",
6961 ok = FALSE;
6962 } else if (game.info.granary_num_inis == 0) {
6963 log_error("No values for granary_food_ini. Using default "
6964 "value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
6967 } else {
6968 int gi;
6969
6970 /* check for <= 0 entries */
6971 for (gi = 0; gi < game.info.granary_num_inis; gi++) {
6972 if (food_ini[gi] <= 0) {
6973 if (gi == 0) {
6975 } else {
6976 food_ini[gi] = food_ini[gi - 1];
6977 }
6978 log_error("Bad value for granary_food_ini[%i]. Using %i.",
6979 gi, food_ini[gi]);
6980 }
6982 }
6983 }
6984 free(food_ini);
6985 }
6986
6987 if (ok) {
6993 "civstyle.granary_food_inc");
6994
7001 "civstyle.min_city_center_%s",
7004 }
7005
7006 if (ok) {
7007 const char *tus_text;
7008
7014 "civstyle.init_vis_radius_sq");
7015
7021 "civstyle.init_city_radius_sq");
7022
7024 "civstyle.gold_upkeep_style");
7029 "Unknown gold upkeep style \"%s\"",
7030 tus_text);
7031 ok = FALSE;
7032 }
7033
7035 = secfile_lookup_bool_default(file, FALSE, "civstyle.homeless_gold_upkeep");
7036
7040 "Cannot have homeless_gold_upkeep while gold_upkeep_style \"City\".");
7041 ok = FALSE;
7042 }
7043
7045 "civstyle.output_granularity");
7046
7048 = secfile_lookup_bool_default(file, FALSE, "civstyle.airlift_from_always_enabled");
7049
7051 = secfile_lookup_bool_default(file, TRUE, "civstyle.airlift_to_always_enabled");
7052
7053 /* section: wonder_visibility */
7054 if (ok) {
7055 const char *text;
7056
7057 text = secfile_lookup_str_default(file,
7059 "wonder_visibility.small_wonders");
7060
7065 "Unknown wonder visibility type \"%s\"",
7066 text);
7067 ok = FALSE;
7068 }
7069 }
7070
7071 /* section: illness */
7074 "illness.illness_on");
7080 "illness.illness_base_factor");
7086 "illness.illness_min_size");
7092 "illness.illness_trade_infection");
7098 "illness.illness_pollution_factor");
7099
7100 /* section: incite_cost */
7106 "incite_cost.base_incite_cost");
7112 "incite_cost.improvement_factor");
7118 "incite_cost.unit_factor");
7124 "incite_cost.total_factor");
7125 }
7126
7127 if (ok) {
7128 const char *tus_text;
7129
7130 /* section: combat_rules */
7133 "combat_rules.tired_attack");
7134
7137 "combat_rules.only_killing_makes_veteran");
7138
7141 "combat_rules.only_real_fight_makes_veteran");
7142
7145 "combat_rules.combat_odds_scaled_veterancy");
7146
7149 "combat_rules.damage_reduces_bombard_rate");
7150
7153 "combat_rules.low_firepower_badwallattacker");
7156 "combat_rules.low_firepower_pearl_harbour");
7159 "combat_rules.low_firepower_combat_bonus");
7162 "combat_rules.low_firepower_nonnat_bombard");
7163
7168 "combat_rules.nuke_pop_loss_pct");
7169
7174 "combat_rules.nuke_defender_survival_chance_pct");
7175
7176 /* section: borders */
7182 "borders.radius_sq_city");
7188 "borders.size_effect");
7189
7195 "borders.radius_sq_city_permanent");
7196
7197 /* section: research */
7199 "research.tech_cost_style");
7204 "Unknown tech cost style \"%s\"",
7205 tus_text);
7206 ok = FALSE;
7207 }
7208
7210 "research.tech_leakage");
7215 "Unknown tech leakage \"%s\"",
7216 tus_text);
7217 ok = FALSE;
7218 }
7221 log_error("Only tech_leakage \"%s\" supported with "
7222 "tech_cost_style \"%s\". ",
7225 log_error("Switching to tech_leakage \"%s\".",
7228 }
7234 "research.base_tech_cost");
7235
7237 "research.tech_upkeep_style");
7238
7240
7243 "Unknown tech upkeep style \"%s\"",
7244 tus_text);
7245 ok = FALSE;
7246 }
7247 }
7248
7249 if (ok) {
7255 "research.tech_upkeep_divider");
7256
7257 sval = secfile_lookup_str_default(file, NULL, "research.free_tech_method");
7258 if (sval == NULL) {
7260 "No free_tech_method given");
7261 ok = FALSE;
7262 } else {
7266 "Bad value %s for free_tech_method.", sval);
7267 ok = FALSE;
7268 }
7269 }
7270 }
7271
7272 if (ok) {
7273 int cf;
7274
7275 /* section: culture */
7278 "culture.victory_min_points");
7281 "culture.victory_lead_pct");
7284 "culture.migration_pml");
7287 "culture.history_interest_pml");
7288
7289 /* section: calendar */
7292 "calendar.skip_year_0");
7295 "calendar.start_year");
7297 = secfile_lookup_int_default(file, 0, "calendar.fragments");
7298
7301 "Too many calendar fragments. Max is %d",
7303 ok = FALSE;
7305 }
7309 "calendar.positive_label"));
7313 "calendar.negative_label"));
7314
7315 for (cf = 0; cf < game.calendar.calendar_fragments; cf++) {
7316 const char *fname;
7317
7318 fname = secfile_lookup_str_default(file, NULL, "calendar.fragment_name%d", cf);
7319 if (fname != NULL) {
7322 }
7323 }
7324 }
7325
7326 if (ok) {
7327 /* section playercolors */
7328 struct rgbcolor *prgbcolor = NULL;
7329 bool color_read = TRUE;
7330
7331 /* Check if the player list is defined and empty. */
7332 if (playercolor_count() != 0) {
7333 ok = FALSE;
7334 } else {
7335 i = 0;
7336
7337 while (color_read) {
7338 prgbcolor = NULL;
7339
7340 color_read = rgbcolor_load(file, &prgbcolor, "playercolors.colorlist%d", i);
7341 if (color_read) {
7343 }
7344
7345 i++;
7346 }
7347
7348 if (playercolor_count() == 0) {
7349 ruleset_error(NULL, LOG_ERROR, "No player colors defined!");
7350 ok = FALSE;
7351 }
7352
7353 if (ok) {
7355 if (!rgbcolor_load(file, &game.plr_bg_color, "playercolors.background")) {
7357 "No background player color defined! (%s)",
7358 secfile_error());
7359 ok = FALSE;
7360 }
7361 }
7362 }
7363 }
7364
7365 if (ok) {
7366 /* section: teams */
7367 svec = secfile_lookup_str_vec(file, &teams, "teams.names");
7368 if (team_slot_count() < teams) {
7370 }
7372 for (i = 0; i < teams; i++) {
7374 }
7375 free(svec);
7376
7378 nval = (NULL != sec ? section_list_size(sec) : 0);
7379 if (nval > MAX_DISASTER_TYPES) {
7380 int num = nval; /* No "size_t" to printf */
7381
7383 "\"%s\": Too many disaster types (%d, max %d)",
7384 filename, num, MAX_DISASTER_TYPES);
7386 ok = FALSE;
7387 } else {
7389 }
7390 }
7391
7392 if (ok) {
7394 int id = disaster_index(pdis);
7395 int j;
7396 size_t eff_count;
7397 struct requirement_vector *reqs;
7398 const char *sec_name = section_name(section_list_get(sec, id));
7399
7400 if (!ruleset_load_names(&pdis->name, NULL, file, sec_name)) {
7402 "\"%s\": Cannot load disaster names",
7403 filename);
7404 ok = FALSE;
7405 break;
7406 }
7407
7409 if (reqs == NULL) {
7410 ok = FALSE;
7411 break;
7412 }
7414
7416 "%s.frequency", sec_name);
7417
7418 svec = secfile_lookup_str_vec(file, &eff_count, "%s.effects", sec_name);
7419
7420 BV_CLR_ALL(pdis->effects);
7421 for (j = 0; j < eff_count; j++) {
7422 const char *dsval = svec[j];
7424
7426
7429 "\"%s\" disaster \"%s\": unknown effect \"%s\".",
7430 filename, disaster_rule_name(pdis), dsval);
7431 ok = FALSE;
7432 break;
7433 } else {
7434 BV_SET(pdis->effects, effect);
7435 }
7436 }
7437
7438 free(svec);
7439
7440 if (!ok) {
7441 break;
7442 }
7445 }
7446
7447 if (ok) {
7449
7451 int id = achievement_index(pach);
7452 const char *sec_name = section_name(section_list_get(sec, id));
7453 const char *typename;
7454 const char *msg;
7455
7456 typename = secfile_lookup_str_default(file, NULL, "%s.type", sec_name);
7457
7458 pach->type = achievement_type_by_name(typename, fc_strcasecmp);
7459 if (!achievement_type_is_valid(pach->type)) {
7461 "Achievement has unknown type \"%s\".",
7462 typename != NULL ? typename : "(NULL)");
7463 ok = FALSE;
7464 }
7465
7466 if (ok) {
7468 "%s.unique", sec_name);
7469
7471 "%s.value", sec_name);
7472 pach->culture = secfile_lookup_int_default(file, 0,
7473 "%s.culture", sec_name);
7474
7475 msg = secfile_lookup_str_default(file, NULL, "%s.first_msg", sec_name);
7476 if (msg == NULL) {
7478 "Achievement %s has no first msg!", sec_name);
7479 ok = FALSE;
7480 } else {
7481 pach->first_msg = fc_strdup(msg);
7482 }
7483 }
7484
7485 if (ok) {
7486 msg = secfile_lookup_str_default(file, NULL, "%s.cons_msg", sec_name);
7487 if (msg == NULL) {
7488 if (!pach->unique) {
7490 "Achievement %s has no msg for consecutive gainers!",
7491 sec_name);
7492 ok = FALSE;
7493 }
7494 } else {
7495 pach->cons_msg = fc_strdup(msg);
7496 }
7497 }
7498
7499 if (!ok) {
7500 break;
7501 }
7504 }
7505
7506 if (ok) {
7507 for (i = 0; (name = secfile_lookup_str_default(file, NULL,
7508 "trade.settings%d.type",
7509 i)); i++) {
7511
7512 if (type == TRT_LAST) {
7514 "\"%s\" unknown trade route type \"%s\".",
7515 filename, name);
7516 ok = FALSE;
7517 } else {
7519 const char *cancelling;
7520 const char *bonus;
7521
7522 set->trade_pct = secfile_lookup_int_default(file, 100,
7523 "trade.settings%d.pct", i);
7524 cancelling = secfile_lookup_str_default(file, "Active",
7525 "trade.settings%d.cancelling", i);
7527 if (set->cancelling == TRI_LAST) {
7529 "\"%s\" unknown trade route cancelling type \"%s\".",
7530 filename, cancelling);
7531 ok = FALSE;
7532 }
7533
7534 bonus = secfile_lookup_str_default(file, "None", "trade.settings%d.bonus", i);
7535
7537
7540 "\"%s\" unknown trade route bonus type \"%s\".",
7541 filename, bonus);
7542 ok = FALSE;
7543 }
7544 }
7545 }
7546 }
7547
7548 if (ok) {
7549 const char *str;
7550 bool reveal_default = FALSE;
7551
7553 = secfile_lookup_int_default(file, 0, "trade.min_trade_route_val");
7554
7555 if (compat->compat_mode && compat->version < RSFORMAT_3_2) {
7556 /* Old hardcoded behavior was to reveal the trade partner. */
7558 }
7559
7562 "trade.reveal_trade_partner");
7563
7566 "trade.goods_selection");
7567
7569
7572 "\"%s\" goods selection method \"%s\" unknown.",
7573 filename, str);
7574 ok = FALSE;
7575 }
7576 }
7577
7578 if (ok) {
7580
7582 int id = goods_index(pgood);
7583 const char *sec_name = section_name(section_list_get(sec, id));
7584 struct requirement_vector *reqs;
7585 const char **slist;
7586 int j;
7587
7589 if (reqs == NULL) {
7590 ok = FALSE;
7591 break;
7592 }
7594
7595 pgood->from_pct = secfile_lookup_int_default(file, 100,
7596 "%s.from_pct", sec_name);
7597 pgood->to_pct = secfile_lookup_int_default(file, 100,
7598 "%s.to_pct", sec_name);
7599 pgood->onetime_pct = secfile_lookup_int_default(file, 100,
7600 "%s.onetime_pct", sec_name);
7601
7602 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
7603 BV_CLR_ALL(pgood->flags);
7604 for (j = 0; j < nval; j++) {
7605 enum goods_flag_id flag;
7606
7607 sval = slist[j];
7609 if (!goods_flag_id_is_valid(flag)) {
7610 ruleset_error(NULL, LOG_ERROR, "\"%s\" good \"%s\": unknown flag \"%s\".",
7611 filename, goods_rule_name(pgood), sval);
7612 ok = FALSE;
7613 break;
7614 } else {
7615 BV_SET(pgood->flags, flag);
7616 }
7617 }
7618 free(slist);
7619
7620 pgood->helptext = lookup_strvec(file, sec_name, "helptext");
7623 }
7624
7625 if (ok) {
7627
7628 if (sec != NULL) {
7629 int num = section_list_size(sec);
7630
7631 for (i = 0; i < num; i++) {
7632 const char *sec_name = section_name(section_list_get(sec, i));
7633 const char *clause_name = secfile_lookup_str_default(file, NULL,
7634 "%s.type", sec_name);
7636 struct clause_info *info;
7637 struct requirement_vector *reqs;
7638
7639 if (!clause_type_is_valid(type)) {
7641 "\"%s\" unknown clause type \"%s\".",
7642 filename, clause_name);
7643 ok = FALSE;
7644 break;
7645 }
7646
7647 info = clause_info_get(type);
7648
7649 if (info->enabled) {
7651 "\"%s\" duplicate clause type \"%s\" definition.",
7652 filename, clause_name);
7653 ok = FALSE;
7654 break;
7655 }
7656
7657 reqs = lookup_req_list(file, compat, sec_name, "giver_reqs", clause_name);
7658 if (reqs == NULL) {
7659 ok = FALSE;
7660 break;
7661 }
7663
7664 reqs = lookup_req_list(file, compat, sec_name, "receiver_reqs", clause_name);
7665 if (reqs == NULL) {
7666 ok = FALSE;
7667 break;
7668 }
7670
7671 info->enabled = TRUE;
7672 }
7673 }
7675 }
7676
7677 if (ok) {
7679
7680 if (sec != NULL) {
7681 int num = section_list_size(sec);
7682 int curr;
7683
7684 for (curr = 0; curr < num; curr++) {
7685
7686 struct counter *pcount = counter_by_id(curr);
7687 const char *sec_name = section_name(section_list_get(sec, curr));
7688 const char *counter_type = secfile_lookup_str_default(file, NULL,
7689 "%s.type",
7690 sec_name);
7691
7694 if (!counter_behavior_is_valid(cb)) {
7696 "\"%s\" unknown counter type \"%s\".",
7697 filename, counter_type);
7698 ok = FALSE;
7699 break;
7700 }
7701
7702 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
7704 "\"%s\": Cannot load counter names",
7705 filename);
7706 ok = FALSE;
7707 break;
7708 }
7709
7710 pcount->helptext = lookup_strvec(file, sec_name, "helptext");
7711 pcount->type = cb;
7712 if (!secfile_lookup_int(file, &pcount->checkpoint,
7713 "%s.checkpoint", sec_name)) {
7714
7716 "\"%s\": No checkpoint value",
7717 filename);
7718 ok = FALSE;
7719 break;
7720 }
7721
7722 pcount->target = CTGT_CITY;
7723 pcount->index = curr;
7724 pcount->def = secfile_lookup_int_default(file, 0,
7725 "%s.def",
7726 sec_name);
7728 }
7729 }
7730 }
7731
7732 /* secfile_check_unused() is not here, but only after also settings section
7733 * has been loaded. */
7734
7735 return ok;
7736}
7737
7738/**********************************************************************/
7741static bool load_ruleset_actions(struct section_file *file,
7742 struct section_file *gamefile,
7743 struct rscompat_info *compat)
7744{
7745 bool ok = TRUE;
7746 const char *filename = secfile_name(file);
7747 struct section_list *sec;
7749 struct requirement_vector *reqs;
7750
7751 /* Auto attack. */
7752
7753 /* Action auto performers aren't ready to be exposed in the ruleset
7754 * yet. The behavior when two action auto performers for the same
7755 * cause can fire isn't set in stone yet. How is one of them chosen?
7756 * What if all the actions of the chosen action auto performer turned
7757 * out to be illegal but one of the other action auto performers that
7758 * fired has legal actions? These issues can decide what other action
7759 * rules action auto performers can represent in the future. Deciding
7760 * should therefore wait until a rule needs action auto performers to
7761 * work a certain way. */
7762 /* Only one action auto performer, ACTION_AUTO_MOVED_ADJ, is caused
7763 * by AAPC_UNIT_MOVED_ADJ. It is therefore safe to expose the full
7764 * requirement vector to the ruleset. */
7765
7766 /* A unit moved next to this unit and the autoattack server setting
7767 * is enabled. */
7770
7771 reqs = lookup_req_list(file, compat,
7772 "auto_attack", "if_attacker",
7773 "auto_attack");
7774 if (reqs == NULL) {
7775 ok = FALSE;
7776 } else {
7778
7780 "auto_attack.attack_actions",
7781 filename)) {
7782 /* Failed to load auto attack actions */
7784 "\"%s\": %s: failed load %s.",
7785 filename, "auto_attack", "attack_actions");
7786 ok = FALSE;
7787 }
7788 }
7789
7790 /* Section: actions */
7791 if (ok) {
7792 action_iterate(act_id) {
7793 struct action *paction = action_by_number(act_id);
7794
7795 if (!load_action_blocked_by_list(file, filename, paction)) {
7796 ok = FALSE;
7797 break;
7798 }
7800
7801 if (ok) {
7802 if (!lookup_bv_actions(file, filename,
7804 "actions.diplchance_initial_odds")) {
7805 ok = FALSE;
7806 }
7807 }
7808
7809 if (ok) {
7810 /* If the "Poison City" action or the "Poison City Escape" action
7811 * should empty the granary. */
7812 /* TODO: empty granary and reduce population should become separate
7813 * action effect flags when actions are generalized. */
7817 "actions.poison_empties_food_stock");
7818
7819 /* If the "Steal Maps" action or the "Steal Maps Escape" action always
7820 * will reveal all cities when successful. */
7824 "actions.steal_maps_reveals_all_cities");
7825
7826 /* Allow setting certain properties for some actions before
7827 * generalized actions. */
7828 action_iterate(act_id) {
7829 if (!load_action_range(file, act_id)) {
7830 ok = FALSE;
7831 } else if (!load_action_kind(file, act_id)) {
7832 ok = FALSE;
7833 } else if (!load_action_actor_consuming_always(file, act_id)) {
7834 ok = FALSE;
7835 } else {
7836 load_action_ui_name(file, act_id,
7839 }
7840
7841 if (!ok) {
7842 break;
7843 }
7845
7846 if (ok && compat->compat_mode && compat->version < RSFORMAT_3_2) {
7847 secfile_entry_ignore_by_path(file, "actions.ui_name_clean_pollution");
7848 secfile_entry_ignore_by_path(file, "actions.ui_name_clean_fallout");
7849 }
7850 }
7851
7852 if (ok) {
7853 /* The quiet (don't auto generate help for) property of all actions
7854 * live in a single enum vector. This avoids generic action
7855 * expectations. */
7856 if (secfile_entry_by_path(file, "actions.quiet_actions")) {
7858 size_t asize;
7859 int j;
7860
7863 "actions.quiet_actions");
7864
7865 if (!quiet_actions) {
7866 /* Entity exists but couldn't read it. */
7868 "\"%s\": actions.quiet_actions: bad action list",
7869 filename);
7870
7871 ok = FALSE;
7872 } else {
7873 for (j = 0; j < asize; j++) {
7874 /* Don't auto generate help text for this action. */
7876 }
7877
7879 }
7880 }
7881 }
7882
7883 if (ok) {
7884 /* Hard code action sub results for now. */
7885
7886 /* Unit Enter Hut */
7888 BV_SET(paction->sub_results, ACT_SUB_RES_HUT_ENTER);
7898
7899 /* Unit Frighten Hut */
7911
7912 /* Unit May Embark */
7913 action_iterate(act_id) {
7914 struct action *paction = action_by_number(act_id);
7915
7917 "civstyle.paradrop_to_transport")
7920 BV_SET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK);
7921 }
7922
7923 /* Embark actions will always embark, not maybe embark. */
7925
7926 /* Non Lethal bombard */
7933 }
7934 }
7935
7936 if (ok) {
7937 /* Forced actions after another action was successfully performed. */
7938
7939 if (!load_action_post_success_force(file, filename,
7943 ok = FALSE;
7944 } else if (!load_action_post_success_force(file, filename,
7947 ACTION_ATTACK))) {
7948 ok = FALSE;
7949 } else if (!load_action_post_success_force(file, filename,
7952 ACTION_ATTACK2))) {
7953 ok = FALSE;
7954 } else if (!load_action_post_success_force(file, filename,
7958 ok = FALSE;
7959 } else if (!load_action_post_success_force(file, filename,
7963 ok = FALSE;
7964 }
7965
7966 /* No "Suicide Attack". Can't act when dead. */
7967 }
7968
7969 if (ok) {
7970 /* The city that made the unit's current tile native is gone.
7971 * Evaluated against an adjacent tile. */
7973 auto_perf->cause = AAPC_CITY_GONE;
7974
7975 /* I have no objections to moving this out of game's actions to
7976 * cities.ruleset, units.ruleset or an other location in game.ruleset
7977 * you find more suitable. -- Sveinung */
7979 "actions.escape_city", filename)) {
7980 ok = FALSE;
7981 }
7982 }
7983
7984 if (ok) {
7985 /* The unit's stack has been defeated and is scheduled for execution
7986 * but the unit has the CanEscape unit type flag.
7987 * Evaluated against an adjacent tile. */
7990
7991 /* I have no objections to moving this out of game's actions to
7992 * cities.ruleset, units.ruleset or an other location in game.ruleset
7993 * you find more suitable. -- Sveinung */
7995 "actions.unit_stack_death", filename)) {
7996 ok = FALSE;
7997 }
7998 }
7999
8000 if (ok) {
8003
8004 if (sec) {
8005 section_list_iterate(sec, psection) {
8006 struct action_enabler *enabler;
8007 const char *sec_name = section_name(psection);
8008 struct action *paction;
8009 struct requirement_vector *actor_reqs;
8010 struct requirement_vector *target_reqs;
8011 const char *action_text;
8012 const char *orig_name;
8013
8015
8016 orig_name = secfile_lookup_str(file, "%s.action", sec_name);
8017
8019
8020 if (action_text == NULL) {
8022 "\"%s\" [%s] missing action to enable.",
8023 filename, sec_name);
8024 ok = FALSE;
8025 break;
8026 }
8027
8029 if (!paction) {
8031 "\"%s\" [%s] lists unknown action type \"%s\".",
8032 filename, sec_name, action_text);
8033 ok = FALSE;
8034 break;
8035 }
8036
8037 enabler->action = action_id(paction);
8038
8039 actor_reqs = lookup_req_list(file, compat, sec_name, "actor_reqs", action_text);
8040 if (actor_reqs == NULL) {
8041 ok = FALSE;
8042 break;
8043 }
8044
8045 requirement_vector_copy(&enabler->actor_reqs, actor_reqs);
8046
8047 target_reqs = lookup_req_list(file, compat, sec_name, "target_reqs", action_text);
8048 if (target_reqs == NULL) {
8049 ok = FALSE;
8050 break;
8051 }
8052
8053 requirement_vector_copy(&enabler->target_reqs, target_reqs);
8054
8056
8059
8061 }
8062 }
8063
8064 return ok;
8065}
8066
8067/**********************************************************************/
8071static void send_ruleset_unit_classes(struct conn_list *dest)
8072{
8073 struct packet_ruleset_unit_class packet;
8075 int i;
8076
8077 for (i = 0; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
8078 const char *flagname;
8079 const char *helptxt;
8080
8082
8084 if (flagname == NULL) {
8085 fpacket.name[0] = '\0';
8086 } else {
8088 }
8089
8091 if (helptxt == NULL) {
8092 fpacket.helptxt[0] = '\0';
8093 } else {
8094 sz_strlcpy(fpacket.helptxt, helptxt);
8095 }
8096
8098 }
8099
8101 packet.id = uclass_number(c);
8102 sz_strlcpy(packet.name, untranslated_name(&c->name));
8103 sz_strlcpy(packet.rule_name, rule_name_get(&c->name));
8104 packet.min_speed = c->min_speed;
8105 packet.hp_loss_pct = c->hp_loss_pct;
8106 packet.non_native_def_pct = c->non_native_def_pct;
8107 packet.flags = c->flags;
8108
8109 PACKET_STRVEC_COMPUTE(packet.helptext, c->helptext);
8110
8111 lsend_packet_ruleset_unit_class(dest, &packet);
8113}
8114
8115/**********************************************************************/
8119static void send_ruleset_units(struct conn_list *dest)
8120{
8121 struct packet_ruleset_unit packet;
8122#ifdef FREECIV_WEB
8124#endif /* FREECIV_WEB */
8126 int i;
8127
8128 for (i = 0; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
8129 const char *flagname;
8130 const char *helptxt;
8131
8133
8135 if (flagname == NULL) {
8136 fpacket.name[0] = '\0';
8137 } else {
8139 }
8140
8142 if (helptxt == NULL) {
8143 fpacket.helptxt[0] = '\0';
8144 } else {
8145 sz_strlcpy(fpacket.helptxt, helptxt);
8146 }
8147
8149 }
8150
8152 packet.id = utype_number(u);
8153 sz_strlcpy(packet.name, untranslated_name(&u->name));
8154 sz_strlcpy(packet.rule_name, rule_name_get(&u->name));
8155 sz_strlcpy(packet.sound_move, u->sound_move);
8156 sz_strlcpy(packet.sound_move_alt, u->sound_move_alt);
8157 sz_strlcpy(packet.sound_fight, u->sound_fight);
8158 sz_strlcpy(packet.sound_fight_alt, u->sound_fight_alt);
8159 sz_strlcpy(packet.graphic_str, u->graphic_str);
8160 sz_strlcpy(packet.graphic_alt, u->graphic_alt);
8161 sz_strlcpy(packet.graphic_alt2, u->graphic_alt2);
8163 packet.build_cost = u->build_cost;
8164 packet.pop_cost = u->pop_cost;
8165 packet.attack_strength = u->attack_strength;
8166 packet.defense_strength = u->defense_strength;
8167 packet.move_rate = u->move_rate;
8168
8169 i = 0;
8170 requirement_vector_iterate(&u->build_reqs, req) {
8171 packet.build_reqs[i++] = *req;
8173 packet.build_reqs_count = i;
8174
8175 packet.vision_radius_sq = u->vision_radius_sq;
8176 packet.transport_capacity = u->transport_capacity;
8177 packet.hp = u->hp;
8178 packet.firepower = u->firepower;
8179 packet.obsoleted_by = u->obsoleted_by
8180 ? utype_number(u->obsoleted_by)
8181 : utype_count();
8182 packet.converted_to = u->converted_to
8183 ? utype_number(u->converted_to)
8184 : utype_count();
8185 packet.convert_time = u->convert_time;
8186 packet.fuel = u->fuel;
8187 packet.flags = u->flags;
8188 packet.roles = u->roles;
8189 packet.happy_cost = u->happy_cost;
8191 packet.upkeep[o] = u->upkeep[o];
8193 packet.paratroopers_range = u->paratroopers_range;
8194 packet.bombard_rate = u->bombard_rate;
8195 packet.city_size = u->city_size;
8196 packet.city_slots = u->city_slots;
8197 packet.tp_defense = u->tp_defense;
8198 packet.cargo = u->cargo;
8199 packet.targets = u->targets;
8200 packet.embarks = u->embarks;
8201 packet.disembarks = u->disembarks;
8202 packet.vlayer = u->vlayer;
8203
8204 if (u->veteran == NULL) {
8205 /* Use the default veteran system. */
8206 packet.veteran_levels = 0;
8207 } else {
8208 /* Per unit veteran system definition. */
8210
8211 for (i = 0; i < packet.veteran_levels; i++) {
8212 const struct veteran_level *vlevel = utype_veteran_level(u, i);
8213
8215 packet.power_fact[i] = vlevel->power_fact;
8216 packet.move_bonus[i] = vlevel->move_bonus;
8217 packet.base_raise_chance[i] = vlevel->base_raise_chance;
8218 packet.work_raise_chance[i] = vlevel->work_raise_chance;
8219 }
8220 }
8221 PACKET_STRVEC_COMPUTE(packet.helptext, u->helptext);
8222
8223 packet.worker = u->adv.worker;
8224
8225#ifdef FREECIV_WEB
8226 web_packet.id = utype_number(u);
8227
8228 BV_CLR_ALL(web_packet.utype_actions);
8229
8230 action_iterate(act) {
8231 if (utype_can_do_action(u, act)) {
8232 BV_SET(web_packet.utype_actions, act);
8233 }
8235#endif /* FREECIV_WEB */
8236
8237 lsend_packet_ruleset_unit(dest, &packet);
8239
8240 combat_bonus_list_iterate(u->bonuses, pbonus) {
8242
8243 bonuspacket.unit = packet.id;
8244 bonuspacket.flag = pbonus->flag;
8245 bonuspacket.type = pbonus->type;
8246 bonuspacket.value = pbonus->value;
8247 bonuspacket.quiet = pbonus->quiet;
8248
8252}
8253
8254/**********************************************************************/
8258static void send_ruleset_specialists(struct conn_list *dest)
8259{
8260 struct packet_ruleset_specialist packet;
8261
8264 int j;
8265
8266 packet.id = spec_id;
8268 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
8272 j = 0;
8274 packet.reqs[j++] = *preq;
8276 packet.reqs_count = j;
8277
8279
8280 lsend_packet_ruleset_specialist(dest, &packet);
8282}
8283/**********************************************************************/
8286static void send_ruleset_tech_classes(struct conn_list *dest)
8287{
8288 struct packet_ruleset_tech_class packet;
8289
8291 packet.id = ptclass->idx;
8292 sz_strlcpy(packet.name, untranslated_name(&ptclass->name));
8293 sz_strlcpy(packet.rule_name, rule_name_get(&ptclass->name));
8294 packet.cost_pct = ptclass->cost_pct;
8295
8296 lsend_packet_ruleset_tech_class(dest, &packet);
8298}
8299
8300/**********************************************************************/
8304static void send_ruleset_techs(struct conn_list *dest)
8305{
8306 struct packet_ruleset_tech packet;
8308 int i;
8309
8310 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
8311 const char *flagname;
8312 const char *helptxt;
8313
8314 fpacket.id = i + TECH_USER_1;
8315
8317 if (flagname == NULL) {
8318 fpacket.name[0] = '\0';
8319 } else {
8321 }
8322
8324 if (helptxt == NULL) {
8325 fpacket.helptxt[0] = '\0';
8326 } else {
8327 sz_strlcpy(fpacket.helptxt, helptxt);
8328 }
8329
8331 }
8332
8333 advance_iterate(a) {
8334 packet.id = advance_number(a);
8335 packet.removed = !valid_advance(a);
8336 if (a->tclass == NULL) {
8337 packet.tclass = 0;
8338 } else {
8339 packet.tclass = a->tclass->idx;
8340 }
8341 sz_strlcpy(packet.name, untranslated_name(&a->name));
8342 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8343 sz_strlcpy(packet.graphic_str, a->graphic_str);
8344 sz_strlcpy(packet.graphic_alt, a->graphic_alt);
8345
8346 /* Current size of the packet's research_reqs requirement vector. */
8347 i = 0;
8348
8349 /* The requirements req1 and req2 are needed to research a tech. Send
8350 * them in the research_reqs requirement vector. Range is set to player
8351 * since pooled research is configurable. */
8352
8353 if ((a->require[AR_ONE] != A_NEVER)
8354 && advance_number(a->require[AR_ONE]) > A_NONE) {
8355 packet.research_reqs[i++]
8357 FALSE, TRUE, FALSE,
8358 advance_number(a->require[AR_ONE]));
8359 }
8360
8361 if ((a->require[AR_TWO] != A_NEVER)
8362 && advance_number(a->require[AR_TWO]) > A_NONE) {
8363 packet.research_reqs[i++]
8365 FALSE, TRUE, FALSE,
8366 advance_number(a->require[AR_TWO]));;
8367 }
8368
8369 /* The requirements of the tech's research_reqs also goes in the
8370 * packet's research_reqs requirement vector. */
8371 requirement_vector_iterate(&a->research_reqs, req) {
8372 packet.research_reqs[i++] = *req;
8374
8375 /* The packet's research_reqs should contain req1, req2 and the
8376 * requirements of the tech's research_reqs. */
8377 packet.research_reqs_count = i;
8378
8379 packet.root_req = a->require[AR_ROOT]
8380 ? advance_number(a->require[AR_ROOT])
8381 : advance_count();
8382
8383 packet.flags = a->flags;
8384 packet.cost = a->cost;
8385 packet.num_reqs = a->num_reqs;
8386 PACKET_STRVEC_COMPUTE(packet.helptext, a->helptext);
8387
8388 lsend_packet_ruleset_tech(dest, &packet);
8390}
8391
8392/**********************************************************************/
8395static void send_ruleset_counters(struct conn_list *dest)
8396{
8398 struct packet_ruleset_counter packet;
8399
8400 sz_strlcpy(packet.name, untranslated_name(&pcount->name));
8401 sz_strlcpy(packet.rule_name, rule_name_get(&pcount->name));
8402 packet.checkpoint = pcount->checkpoint;
8403 packet.behavior = pcount->type;
8404 packet.type = pcount->target;
8405 packet.def = pcount->def;
8406
8407 PACKET_STRVEC_COMPUTE(packet.helptext, pcount->helptext);
8408 lsend_packet_ruleset_counter(dest, &packet);
8410}
8411
8412/**********************************************************************/
8416static void send_ruleset_buildings(struct conn_list *dest)
8417{
8418 int i;
8419
8420 for (i = 0; i < MAX_NUM_USER_BUILDING_FLAGS; i++) {
8422 const char *flagname;
8423 const char *helptxt;
8424
8426
8428 if (flagname == NULL) {
8429 fpacket.name[0] = '\0';
8430 } else {
8432 }
8433
8435 if (helptxt == NULL) {
8436 fpacket.helptxt[0] = '\0';
8437 } else {
8438 sz_strlcpy(fpacket.helptxt, helptxt);
8439 }
8440
8442 }
8443
8445 struct packet_ruleset_building packet;
8446 int j;
8447
8448 packet.id = improvement_number(b);
8449 packet.genus = b->genus;
8450 sz_strlcpy(packet.name, untranslated_name(&b->name));
8451 sz_strlcpy(packet.rule_name, rule_name_get(&b->name));
8452 sz_strlcpy(packet.graphic_str, b->graphic_str);
8453 sz_strlcpy(packet.graphic_alt, b->graphic_alt);
8454 sz_strlcpy(packet.graphic_alt2, b->graphic_alt2);
8455 j = 0;
8456 requirement_vector_iterate(&b->reqs, preq) {
8457 packet.reqs[j++] = *preq;
8459 packet.reqs_count = j;
8460 j = 0;
8461 requirement_vector_iterate(&b->obsolete_by, pobs) {
8462 packet.obs_reqs[j++] = *pobs;
8464 packet.obs_count = j;
8465 packet.build_cost = b->build_cost;
8466 packet.upkeep = b->upkeep;
8467 packet.sabotage = b->sabotage;
8468 packet.flags = b->flags;
8469 sz_strlcpy(packet.soundtag, b->soundtag);
8470 sz_strlcpy(packet.soundtag_alt, b->soundtag_alt);
8471 sz_strlcpy(packet.soundtag_alt2, b->soundtag_alt2);
8472 PACKET_STRVEC_COMPUTE(packet.helptext, b->helptext);
8473
8474 lsend_packet_ruleset_building(dest, &packet);
8476}
8477
8478/**********************************************************************/
8482static void send_ruleset_terrain(struct conn_list *dest)
8483{
8484 struct packet_ruleset_terrain packet;
8486 int i;
8487
8489
8490 for (i = 0; i < MAX_NUM_USER_TER_FLAGS; i++) {
8491 const char *flagname;
8492 const char *helptxt;
8493
8494 fpacket.id = i + TER_USER_1;
8495
8497 if (flagname == NULL) {
8498 fpacket.name[0] = '\0';
8499 } else {
8501 }
8502
8504 if (helptxt == NULL) {
8505 fpacket.helptxt[0] = '\0';
8506 } else {
8507 sz_strlcpy(fpacket.helptxt, helptxt);
8508 }
8509
8511 }
8512
8513 terrain_type_iterate(pterrain) {
8514 packet.id = terrain_number(pterrain);
8515 packet.tclass = pterrain->tclass;
8516 packet.native_to = pterrain->native_to;
8517
8518 sz_strlcpy(packet.name, untranslated_name(&pterrain->name));
8519 sz_strlcpy(packet.rule_name, rule_name_get(&pterrain->name));
8520 sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
8521 sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
8522 sz_strlcpy(packet.graphic_alt2, pterrain->graphic_alt2);
8523
8524 packet.movement_cost = pterrain->movement_cost;
8525 packet.defense_bonus = pterrain->defense_bonus;
8526
8528 packet.output[o] = pterrain->output[o];
8530
8531 packet.num_resources = 0;
8532 terrain_resources_iterate(pterrain, res, freq) {
8533 packet.resources[packet.num_resources] = extra_number(res);
8534 packet.resource_freq[packet.num_resources] = freq;
8535 packet.num_resources++;
8537
8539 packet.road_output_incr_pct[o] = pterrain->road_output_incr_pct[o];
8541
8542 packet.base_time = pterrain->base_time;
8543 packet.road_time = pterrain->road_time;
8544
8545 packet.cultivate_result = (pterrain->cultivate_result
8546 ? terrain_number(pterrain->cultivate_result)
8547 : terrain_count());
8548 packet.cultivate_time = pterrain->cultivate_time;
8549
8550 packet.plant_result = (pterrain->plant_result
8551 ? terrain_number(pterrain->plant_result)
8552 : terrain_count());
8553 packet.plant_time = pterrain->plant_time;
8554
8555 packet.irrigation_food_incr = pterrain->irrigation_food_incr;
8556 packet.irrigation_time = pterrain->irrigation_time;
8557
8558 packet.mining_shield_incr = pterrain->mining_shield_incr;
8559 packet.mining_time = pterrain->mining_time;
8560
8561 packet.animal = (pterrain->animal == NULL ? -1 : utype_number(pterrain->animal));
8562 packet.transform_result = (pterrain->transform_result
8563 ? terrain_number(pterrain->transform_result)
8564 : terrain_count());
8565 packet.placing_time = pterrain->placing_time;
8566 packet.pillage_time = pterrain->pillage_time;
8567 packet.transform_time = pterrain->transform_time;
8568
8570 for (i = 0; i < game.control.num_extra_types; i++) {
8571 packet.extra_removal_times[i] = pterrain->extra_removal_times[i];
8572 }
8573
8574 packet.flags = pterrain->flags;
8575
8576 packet.color_red = pterrain->rgb->r;
8577 packet.color_green = pterrain->rgb->g;
8578 packet.color_blue = pterrain->rgb->b;
8579
8580 PACKET_STRVEC_COMPUTE(packet.helptext, pterrain->helptext);
8581
8582 lsend_packet_ruleset_terrain(dest, &packet);
8584}
8585
8586/**********************************************************************/
8589static void send_ruleset_resources(struct conn_list *dest)
8590{
8591 struct packet_ruleset_resource packet;
8592
8594 packet.id = extra_index(presource);
8595
8597 packet.output[o] = presource->data.resource->output[o];
8599
8600 lsend_packet_ruleset_resource(dest, &packet);
8602}
8603
8604/**********************************************************************/
8608static void send_ruleset_extras(struct conn_list *dest)
8609{
8610 int i;
8611
8612 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
8614 const char *flagname;
8615 const char *helptxt;
8616
8618
8620 if (flagname == NULL) {
8621 fpacket.name[0] = '\0';
8622 } else {
8624 }
8625
8627 if (helptxt == NULL) {
8628 fpacket.helptxt[0] = '\0';
8629 } else {
8630 sz_strlcpy(fpacket.helptxt, helptxt);
8631 }
8632
8634 }
8635
8637 struct packet_ruleset_extra packet;
8638 int j;
8639
8640 packet.id = extra_number(e);
8641 sz_strlcpy(packet.name, untranslated_name(&e->name));
8642 sz_strlcpy(packet.rule_name, rule_name_get(&e->name));
8643
8644 packet.category = e->category;
8645
8646 BV_CLR_ALL(packet.causes);
8647 for (j = 0; j < EC_COUNT; j++) {
8648 if (is_extra_caused_by(e, j)) {
8649 BV_SET(packet.causes, j);
8650 }
8651 }
8652
8653 BV_CLR_ALL(packet.rmcauses);
8654 for (j = 0; j < ERM_COUNT; j++) {
8655 if (is_extra_removed_by(e, j)) {
8656 BV_SET(packet.rmcauses, j);
8657 }
8658 }
8659
8660 sz_strlcpy(packet.activity_gfx, e->activity_gfx);
8661 sz_strlcpy(packet.act_gfx_alt, e->act_gfx_alt);
8662 sz_strlcpy(packet.act_gfx_alt2, e->act_gfx_alt2);
8663 sz_strlcpy(packet.rmact_gfx, e->rmact_gfx);
8664 sz_strlcpy(packet.rmact_gfx_alt, e->rmact_gfx_alt);
8665 sz_strlcpy(packet.rmact_gfx_alt2, e->rmact_gfx_alt2);
8666 sz_strlcpy(packet.graphic_str, e->graphic_str);
8667 sz_strlcpy(packet.graphic_alt, e->graphic_alt);
8668
8669 j = 0;
8670 requirement_vector_iterate(&e->reqs, preq) {
8671 packet.reqs[j++] = *preq;
8673 packet.reqs_count = j;
8674
8675 j = 0;
8676 requirement_vector_iterate(&e->rmreqs, preq) {
8677 packet.rmreqs[j++] = *preq;
8679 packet.rmreqs_count = j;
8680
8681 packet.appearance_chance = e->appearance_chance;
8682 j = 0;
8683 requirement_vector_iterate(&e->appearance_reqs, preq) {
8684 packet.appearance_reqs[j++] = *preq;
8686 packet.appearance_reqs_count = j;
8687
8688 packet.disappearance_chance = e->disappearance_chance;
8689 j = 0;
8690 requirement_vector_iterate(&e->disappearance_reqs, preq) {
8691 packet.disappearance_reqs[j++] = *preq;
8693 packet.disappearance_reqs_count = j;
8694
8695 packet.visibility_req = e->visibility_req;
8696 packet.buildable = e->buildable;
8697 packet.generated = e->generated;
8698 packet.build_time = e->build_time;
8699 packet.build_time_factor = e->build_time_factor;
8700 packet.removal_time = e->removal_time;
8701 packet.removal_time_factor = e->removal_time_factor;
8702 packet.infracost = e->infracost;
8703 packet.defense_bonus = e->defense_bonus;
8704 packet.eus = e->eus;
8705 packet.no_aggr_near_city = e->no_aggr_near_city;
8706
8707 packet.native_to = e->native_to;
8708
8709 packet.flags = e->flags;
8710 packet.hidden_by = e->hidden_by;
8711 packet.bridged_over = e->bridged_over;
8712 packet.conflicts = e->conflicts;
8713
8714 PACKET_STRVEC_COMPUTE(packet.helptext, e->helptext);
8715
8716 lsend_packet_ruleset_extra(dest, &packet);
8718}
8719
8720/**********************************************************************/
8724static void send_ruleset_bases(struct conn_list *dest)
8725{
8727 struct base_type *b = extra_base_get(pextra);
8728 struct packet_ruleset_base packet;
8729
8730 packet.id = base_number(b);
8731
8732 packet.gui_type = b->gui_type;
8733 packet.border_sq = b->border_sq;
8734 packet.vision_main_sq = b->vision_main_sq;
8735 packet.vision_invis_sq = b->vision_invis_sq;
8736 packet.vision_subs_sq = b->vision_subs_sq;
8737
8738 lsend_packet_ruleset_base(dest, &packet);
8740}
8741
8742/**********************************************************************/
8746static void send_ruleset_roads(struct conn_list *dest)
8747{
8748 struct packet_ruleset_road packet;
8749
8751 struct road_type *r = extra_road_get(pextra);
8752 int j;
8753
8754 packet.id = road_number(r);
8755
8756 packet.gui_type = r->gui_type;
8757
8758 j = 0;
8760 packet.first_reqs[j++] = *preq;
8762 packet.first_reqs_count = j;
8763
8764 packet.move_cost = r->move_cost;
8765 packet.move_mode = r->move_mode;
8766
8768 packet.tile_incr_const[o] = r->tile_incr_const[o];
8769 packet.tile_incr[o] = r->tile_incr[o];
8770 packet.tile_bonus[o] = r->tile_bonus[o];
8772
8773 packet.compat = r->compat;
8774
8775 packet.integrates = r->integrates;
8776 packet.flags = r->flags;
8777
8778 lsend_packet_ruleset_road(dest, &packet);
8780}
8781
8782/**********************************************************************/
8786static void send_ruleset_goods(struct conn_list *dest)
8787{
8788 struct packet_ruleset_goods packet;
8789
8791 int j;
8792
8793 packet.id = goods_number(g);
8794 sz_strlcpy(packet.name, untranslated_name(&g->name));
8795 sz_strlcpy(packet.rule_name, rule_name_get(&g->name));
8796
8797 j = 0;
8798 requirement_vector_iterate(&g->reqs, preq) {
8799 packet.reqs[j++] = *preq;
8801 packet.reqs_count = j;
8802
8803 packet.from_pct = g->from_pct;
8804 packet.to_pct = g->to_pct;
8805 packet.onetime_pct = g->onetime_pct;
8806 packet.flags = g->flags;
8807
8808 PACKET_STRVEC_COMPUTE(packet.helptext, g->helptext);
8809
8810 lsend_packet_ruleset_goods(dest, &packet);
8812}
8813
8814/**********************************************************************/
8818static void send_ruleset_disasters(struct conn_list *dest)
8819{
8820 struct packet_ruleset_disaster packet;
8821
8823 int j;
8824
8825 packet.id = disaster_number(d);
8826
8827 sz_strlcpy(packet.name, untranslated_name(&d->name));
8828 sz_strlcpy(packet.rule_name, rule_name_get(&d->name));
8829
8830 j = 0;
8831 requirement_vector_iterate(&d->reqs, preq) {
8832 packet.reqs[j++] = *preq;
8834 packet.reqs_count = j;
8835
8836 packet.frequency = d->frequency;
8837
8838 packet.effects = d->effects;
8839
8840 lsend_packet_ruleset_disaster(dest, &packet);
8842}
8843
8844/**********************************************************************/
8848static void send_ruleset_achievements(struct conn_list *dest)
8849{
8850 struct packet_ruleset_achievement packet;
8851
8853 packet.id = achievement_number(a);
8854
8855 sz_strlcpy(packet.name, untranslated_name(&a->name));
8856 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8857
8858 packet.type = a->type;
8859 packet.unique = a->unique;
8860 packet.value = a->value;
8861
8862 lsend_packet_ruleset_achievement(dest, &packet);
8864}
8865
8866/**********************************************************************/
8869static void send_ruleset_actions(struct conn_list *dest)
8870{
8871 struct packet_ruleset_action packet;
8872
8873 action_iterate(act) {
8874 struct action *paction = action_by_number(act);
8875
8876 packet.id = act;
8878 packet.quiet = action_by_number(act)->quiet;
8879
8880 packet.result = paction->result;
8881 packet.sub_results = paction->sub_results;
8882 packet.actor_consuming_always = paction->actor_consuming_always;
8883
8884 packet.act_kind = action_by_number(act)->actor_kind;
8885 packet.tgt_kind = action_by_number(act)->target_kind;
8887
8890 packet.blocked_by = action_by_number(act)->blocked_by;
8891
8892 lsend_packet_ruleset_action(dest, &packet);
8894}
8895
8896/**********************************************************************/
8900{
8901 int counter;
8902 struct packet_ruleset_action_enabler packet;
8903
8906
8907 counter = 0;
8908 requirement_vector_iterate(&enabler->actor_reqs, req) {
8909 packet.actor_reqs[counter++] = *req;
8911 packet.actor_reqs_count = counter;
8912
8913 counter = 0;
8914 requirement_vector_iterate(&enabler->target_reqs, req) {
8915 packet.target_reqs[counter++] = *req;
8917 packet.target_reqs_count = counter;
8918
8921}
8922
8923/**********************************************************************/
8928{
8929 int counter;
8930 int id;
8931 struct packet_ruleset_action_auto packet;
8932
8933 id = 0;
8935 packet.id = id++;
8936
8937 packet.cause = aperf->cause;
8938
8939 counter = 0;
8940 requirement_vector_iterate(&aperf->reqs, req) {
8941 packet.reqs[counter++] = *req;
8943 packet.reqs_count = counter;
8944
8945 for (counter = 0;
8946 /* Can't list more actions than all actions. */
8948 /* ACTION_NONE terminates the list. */
8949 && aperf->alternatives[counter] != ACTION_NONE;
8950 counter++) {
8951 packet.alternatives[counter] = aperf->alternatives[counter];
8952 }
8953 packet.alternatives_count = counter;
8954
8955 lsend_packet_ruleset_action_auto(dest, &packet);
8957}
8958
8959/**********************************************************************/
8963static void send_ruleset_trade_routes(struct conn_list *dest)
8964{
8965 struct packet_ruleset_trade packet;
8967
8968 for (type = TRT_NATIONAL; type < TRT_LAST; type++) {
8970
8971 packet.id = type;
8972 packet.trade_pct = set->trade_pct;
8973 packet.cancelling = set->cancelling;
8974 packet.bonus_type = set->bonus_type;
8975
8976 lsend_packet_ruleset_trade(dest, &packet);
8977 }
8978}
8979
8980/**********************************************************************/
8984static void send_ruleset_governments(struct conn_list *dest)
8985{
8986 struct packet_ruleset_government gov;
8988 int j;
8989
8991 /* Send one packet_government */
8992 gov.id = government_number(g);
8993
8994 j = 0;
8995 requirement_vector_iterate(&g->reqs, preq) {
8996 gov.reqs[j++] = *preq;
8998 gov.reqs_count = j;
8999
9000 sz_strlcpy(gov.name, untranslated_name(&g->name));
9001 sz_strlcpy(gov.rule_name, rule_name_get(&g->name));
9002 sz_strlcpy(gov.graphic_str, g->graphic_str);
9003 sz_strlcpy(gov.graphic_alt, g->graphic_alt);
9004 sz_strlcpy(gov.sound_str, g->sound_str);
9005 sz_strlcpy(gov.sound_alt, g->sound_alt);
9006 sz_strlcpy(gov.sound_alt2, g->sound_alt2);
9007 PACKET_STRVEC_COMPUTE(gov.helptext, g->helptext);
9008
9010
9011 /* Send one packet_government_ruler_title per ruler title. */
9013 const struct nation_type *pnation = ruler_title_nation(pruler_title);
9014
9015 title.gov = government_number(g);
9016 title.nation = pnation ? nation_number(pnation) : nation_count();
9017 sz_strlcpy(title.male_title,
9019 sz_strlcpy(title.female_title,
9024}
9025
9026/**********************************************************************/
9030static void send_ruleset_nations(struct conn_list *dest)
9031{
9034 struct packet_ruleset_nation packet;
9035 int i;
9036
9038 i = 0;
9043 i++;
9046
9048 i = 0;
9050 sz_strlcpy(groups_packet.groups[i],
9052 groups_packet.hidden[i] = pgroup->hidden;
9053 i++;
9056
9058 packet.id = nation_number(n);
9059 if (n->translation_domain == NULL) {
9060 packet.translation_domain[0] = '\0';
9061 } else {
9062 sz_strlcpy(packet.translation_domain, n->translation_domain);
9063 }
9064 sz_strlcpy(packet.adjective, untranslated_name(&n->adjective));
9065 sz_strlcpy(packet.rule_name, rule_name_get(&n->adjective));
9066 sz_strlcpy(packet.noun_plural, untranslated_name(&n->noun_plural));
9067 sz_strlcpy(packet.graphic_str, n->flag_graphic_str);
9068 sz_strlcpy(packet.graphic_alt, n->flag_graphic_alt);
9069
9070 i = 0;
9074 i++;
9076 packet.leader_count = i;
9077
9078 packet.style = style_number(n->style);
9079 packet.is_playable = n->is_playable;
9080 packet.barbarian_type = n->barb_type;
9081
9082 sz_strlcpy(packet.legend, n->legend);
9083
9084 i = 0;
9086 packet.sets[i++] = nation_set_number(pset);
9088 packet.nsets = i;
9089
9090 i = 0;
9092 packet.groups[i++] = nation_group_number(pgroup);
9094 packet.ngroups = i;
9095
9096 packet.init_government_id = n->init_government
9097 ? government_number(n->init_government) : government_count();
9098 fc_assert(ARRAY_SIZE(packet.init_techs) == ARRAY_SIZE(n->init_techs));
9099 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9100 if (n->init_techs[i] != A_LAST) {
9101 packet.init_techs[i] = n->init_techs[i];
9102 } else {
9103 break;
9104 }
9105 }
9106 packet.init_techs_count = i;
9107 fc_assert(ARRAY_SIZE(packet.init_units) == ARRAY_SIZE(n->init_units));
9108 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
9109 const struct unit_type *t = n->init_units[i];
9110 if (t) {
9111 packet.init_units[i] = utype_number(t);
9112 } else {
9113 break;
9114 }
9115 }
9116 packet.init_units_count = i;
9118 == ARRAY_SIZE(n->init_buildings));
9119 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9120 if (n->init_buildings[i] != B_LAST) {
9121 /* Impr_type_id to int */
9122 packet.init_buildings[i] = n->init_buildings[i];
9123 } else {
9124 break;
9125 }
9126 }
9127 packet.init_buildings_count = i;
9128
9129 lsend_packet_ruleset_nation(dest, &packet);
9131
9132 /* Send initial values of is_pickable */
9134}
9135
9136/**********************************************************************/
9140static void send_ruleset_styles(struct conn_list *dest)
9141{
9142 struct packet_ruleset_style packet;
9143
9144 styles_iterate(s) {
9145 packet.id = style_index(s);
9146 sz_strlcpy(packet.name, untranslated_name(&s->name));
9147 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
9148
9149 lsend_packet_ruleset_style(dest, &packet);
9151}
9152
9153/**********************************************************************/
9156static void send_ruleset_clauses(struct conn_list *dest)
9157{
9158 struct packet_ruleset_clause packet;
9159 int i;
9160
9161 for (i = 0; i < CLAUSE_COUNT; i++) {
9162 struct clause_info *info = clause_info_get(i);
9163 int j;
9164
9165 packet.type = i;
9166 packet.enabled = info->enabled;
9167
9168 j = 0;
9170 packet.giver_reqs[j++] = *preq;
9172 packet.giver_reqs_count = j;
9173
9174 j = 0;
9176 packet.receiver_reqs[j++] = *preq;
9178 packet.receiver_reqs_count = j;
9179
9180 lsend_packet_ruleset_clause(dest, &packet);
9181 }
9182}
9183
9184/**********************************************************************/
9188static void send_ruleset_multipliers(struct conn_list *dest)
9189{
9190 multipliers_iterate(pmul) {
9191 int j;
9192 struct packet_ruleset_multiplier packet;
9193
9194 packet.id = multiplier_number(pmul);
9195 packet.start = pmul->start;
9196 packet.stop = pmul->stop;
9197 packet.step = pmul->step;
9198 packet.def = pmul->def;
9199 packet.offset = pmul->offset;
9200 packet.factor = pmul->factor;
9201 packet.minimum_turns = pmul->minimum_turns;
9202
9203 sz_strlcpy(packet.name, untranslated_name(&pmul->name));
9204 sz_strlcpy(packet.rule_name, rule_name_get(&pmul->name));
9205
9206 j = 0;
9207 requirement_vector_iterate(&pmul->reqs, preq) {
9208 packet.reqs[j++] = *preq;
9210 packet.reqs_count = j;
9211
9212 PACKET_STRVEC_COMPUTE(packet.helptext, pmul->helptext);
9213
9214 lsend_packet_ruleset_multiplier(dest, &packet);
9216}
9217
9218/**********************************************************************/
9222static void send_ruleset_cities(struct conn_list *dest)
9223{
9225 int k, j;
9226
9227 for (k = 0; k < game.control.num_city_styles; k++) {
9228 city_p.style_id = k;
9229
9230 j = 0;
9232 city_p.reqs[j++] = *preq;
9234 city_p.reqs_count = j;
9235
9238 sz_strlcpy(city_p.graphic, city_styles[k].graphic);
9239 sz_strlcpy(city_p.graphic_alt, city_styles[k].graphic_alt);
9240 sz_strlcpy(city_p.citizens_graphic, city_styles[k].citizens_graphic);
9241
9243 }
9244}
9245
9246/**********************************************************************/
9250static void send_ruleset_musics(struct conn_list *dest)
9251{
9252 struct packet_ruleset_music packet;
9253
9255 int j;
9256
9257 packet.id = pmus->id;
9258
9259 sz_strlcpy(packet.music_peaceful, pmus->music_peaceful);
9260 sz_strlcpy(packet.music_combat, pmus->music_combat);
9261
9262 j = 0;
9264 packet.reqs[j++] = *preq;
9266 packet.reqs_count = j;
9267
9268 lsend_packet_ruleset_music(dest, &packet);
9270}
9271
9272/**********************************************************************/
9276static void send_ruleset_game(struct conn_list *dest)
9277{
9279 int i;
9280
9282
9283 /* Per unit veteran system definition. */
9284 misc_p.veteran_levels = game.veteran->levels;
9285
9286 for (i = 0; i < misc_p.veteran_levels; i++) {
9287 const struct veteran_level *vlevel = game.veteran->definitions + i;
9288
9289 sz_strlcpy(misc_p.veteran_name[i], untranslated_name(&vlevel->name));
9290 misc_p.power_fact[i] = vlevel->power_fact;
9291 misc_p.move_bonus[i] = vlevel->move_bonus;
9292 misc_p.base_raise_chance[i] = vlevel->base_raise_chance;
9293 misc_p.work_raise_chance[i] = vlevel->work_raise_chance;
9294 }
9295
9296 fc_assert(sizeof(misc_p.global_init_techs)
9297 == sizeof(game.rgame.global_init_techs));
9298 fc_assert(ARRAY_SIZE(misc_p.global_init_techs)
9300 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9302 misc_p.global_init_techs[i] = game.rgame.global_init_techs[i];
9303 } else {
9304 break;
9305 }
9306 }
9307 misc_p.global_init_techs_count = i;
9308
9309 fc_assert(ARRAY_SIZE(misc_p.global_init_buildings)
9311 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9313 /* Impr_type_id to int */
9314 misc_p.global_init_buildings[i] =
9316 } else {
9317 break;
9318 }
9319 }
9320 misc_p.global_init_buildings_count = i;
9321
9322 misc_p.default_specialist = DEFAULT_SPECIALIST;
9323
9325
9326 misc_p.background_red = game.plr_bg_color->r;
9327 misc_p.background_green = game.plr_bg_color->g;
9328 misc_p.background_blue = game.plr_bg_color->b;
9329
9331}
9332
9333/**********************************************************************/
9337static void send_ruleset_team_names(struct conn_list *dest)
9338{
9340
9342 const char *name = team_slot_defined_name(tslot);
9343
9344 if (NULL == name) {
9345 /* End of defined names. */
9346 break;
9347 }
9348
9350 sz_strlcpy(team_name_info_p.team_name, name);
9351
9354}
9355
9356/**********************************************************************/
9359static void notify_ruleset_fallback(const char *msg)
9360{
9362}
9363
9364/**********************************************************************/
9367bool load_rulesets(const char *restore, const char *alt, bool compat_mode,
9368 rs_conversion_logger logger,
9369 bool act, bool buffer_script, bool load_luadata)
9370{
9371 set_ruleset_compat_mode(compat_mode);
9372
9373 if (load_rulesetdir(game.server.rulesetdir, compat_mode, logger,
9374 act, buffer_script, load_luadata)) {
9376 return TRUE;
9377 }
9378
9379 if (alt != NULL) {
9380 if (load_rulesetdir(alt, compat_mode, logger, act, buffer_script,
9381 load_luadata)) {
9383
9385 return TRUE;
9386 }
9387 }
9388
9389 /* Fallback to previous one. */
9390 if (restore != NULL) {
9391 if (load_rulesetdir(restore, compat_mode, logger, act, buffer_script, TRUE)) {
9393
9394 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Keeping previous one."));
9395
9397
9398 /* We're in sane state as restoring previous ruleset succeeded,
9399 * but return failure to indicate that this is not what caller
9400 * wanted. */
9401 return FALSE;
9402 }
9403 }
9404
9406
9407 /* Fallback to default one, but not if that's what we tried already */
9411 /* We're in sane state as fallback ruleset loading succeeded,
9412 * but return failure to indicate that this is not what caller
9413 * wanted. */
9415
9416 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Switching to default one."));
9417
9418 return FALSE;
9419 }
9420 }
9421
9422#ifdef FREECIV_WEB
9423 log_normal(_("Cannot load any ruleset. Freeciv-web ruleset is available from "
9424 "https://github.com/freeciv/freeciv-web"));
9425#endif /* FREECIV_WEB */
9426
9427 /* Cannot load even default ruleset, we're in completely unusable state */
9429
9431}
9432
9433/**********************************************************************/
9437{
9438 if (file != NULL) {
9439 secfile_destroy(file);
9440 }
9441}
9442
9443/**********************************************************************/
9452
9453/**********************************************************************/
9457static bool load_rulesetdir(const char *rsdir, bool compat_mode,
9458 rs_conversion_logger logger,
9459 bool act, bool buffer_script, bool load_luadata)
9460{
9463 struct section_file *actionfile;
9464 bool ok = TRUE;
9466
9467 log_normal(_("Loading rulesets."));
9468
9470 compat_info.compat_mode = compat_mode;
9471 compat_info.log_cb = logger;
9472
9474 /* Reset the list of available player colors. */
9478
9479 if (script_buffer != NULL) {
9482 }
9483 if (parser_buffer != NULL) {
9486 }
9487
9488 server.playable_nations = 0;
9489
9491
9492 if (gamefile != NULL) {
9493 /* Needed here to fill compat_info. RSFORMAT_3_2 specific arrangement. */
9495 } else {
9496 ok = FALSE;
9497 }
9498
9500
9501 if (compat_info.version >= RSFORMAT_3_2) {
9503 } else {
9504 actionfile = NULL;
9505 }
9506
9507 buildfile = openload_ruleset_file("buildings", rsdir);
9508 govfile = openload_ruleset_file("governments", rsdir);
9510 terrfile = openload_ruleset_file("terrain", rsdir);
9515
9516 if (load_luadata) {
9518 } else {
9520 }
9521
9522 if (techfile == NULL
9523 || buildfile == NULL
9524 || govfile == NULL
9525 || unitfile == NULL
9526 || terrfile == NULL
9527 || stylefile == NULL
9528 || cityfile == NULL
9529 || nationfile == NULL
9530 || effectfile == NULL
9531 || (actionfile == NULL && (!compat_info.compat_mode || compat_info.version >= RSFORMAT_3_2))
9532 || gamefile == NULL) {
9533 ok = FALSE;
9534 }
9535
9536 if (ok) {
9537 /* Note: Keep load_game_names() first so that compat_info.version is
9538 * correctly initialized. (Currently handled above already) */
9547 }
9548
9549 if (ok) {
9550 /* 3.1 rulesets have no actions.ruleset. */
9551 if (compat_info.compat_mode && compat_info.version < RSFORMAT_3_2) {
9553 } else {
9555 }
9556 }
9557
9558 if (ok) {
9560 }
9561
9562 if (ok) {
9564 }
9565 if (ok) {
9567 }
9568 if (ok) {
9570 }
9571 if (ok) {
9573 }
9574 if (ok) {
9575 /* Terrain must precede nations and units */
9577 }
9578 if (ok) {
9580 }
9581 if (ok) {
9583 }
9584 if (ok) {
9586 }
9587 if (ok) {
9589 }
9590 if (ok) {
9592 }
9593
9594 if (ok) {
9595 /* Init nations we just loaded. */
9597
9598 /* Needed by role_unit_precalcs(). */
9600
9601 /* Prepare caches we want to sanity check. */
9605
9608 }
9609
9610 if (ok) {
9611 /* Only load settings for a sane ruleset */
9612 ok = settings_ruleset(gamefile, "settings", act,
9613 compat_info.compat_mode
9614 && compat_info.version < RSFORMAT_3_2);
9615
9616 if (ok) {
9618 }
9619 }
9620
9632
9633 if (extra_sections) {
9636 }
9637 if (base_sections) {
9640 }
9641 if (road_sections) {
9644 }
9645 if (resource_sections) {
9648 }
9649 if (terrain_sections) {
9652 }
9653
9654 if (ok) {
9656 }
9657
9658 if (ok) {
9659 char **buffer = buffer_script ? &script_buffer : NULL;
9660
9662
9664
9665 ok = (openload_script_file("script", rsdir, buffer, FALSE) == TRI_YES);
9666 }
9667
9668 if (ok) {
9669 enum fc_tristate pret;
9670 char **buffer = buffer_script ? &parser_buffer : NULL;
9671
9672 pret = openload_script_file("parser", rsdir, buffer, compat_info.compat_mode);
9673
9674 if (pret == TRI_MAYBE && buffer_script) {
9676 "-- This file is for lua-functionality for parsing luadata.txt\n-- of this ruleset.");
9677 }
9678
9679 ok = (pret != TRI_NO);
9680 }
9681
9682 if (ok && !buffer_script) {
9683 ok = (openload_script_file("default", rsdir, NULL, FALSE) == TRI_YES);
9684 }
9685
9686 if (ok && act) {
9687 /* Populate remaining caches. */
9694 ptype->unknown_move_cost = utype_unknown_move_cost(ptype);
9698
9699 /* Build advisors unit class cache corresponding to loaded rulesets */
9701 CALL_FUNC_EACH_AI(units_ruleset_init);
9702
9703 /* We may need to adjust the number of AI players
9704 * if the number of available nations changed. */
9706 }
9707
9708 return ok;
9709}
9710
9711/**********************************************************************/
9715{
9716 struct section_file *file;
9717 bool ok = TRUE;
9718
9720 if (file == NULL) {
9722 "Could not load game.ruleset:\n%s",
9723 secfile_error());
9724 ok = FALSE;
9725 }
9726 if (ok) {
9727 settings_ruleset(file, "settings", TRUE, FALSE);
9728 secfile_destroy(file);
9729 }
9730
9731 return ok;
9732}
9733
9734/**********************************************************************/
9737void send_rulesets(struct conn_list *dest)
9738{
9740
9741 /* ruleset_control also indicates to client that ruleset sending starts. */
9743
9744 /* Currently containing control-kind of data of nation sets and groups,
9745 * this too must be sent before any requirement vector may depend on
9746 * that data. */
9748
9749 send_ruleset_game(dest);
9759 send_ruleset_techs(dest);
9762 send_ruleset_units(dest);
9764 send_ruleset_extras(dest);
9765 send_ruleset_bases(dest);
9766 send_ruleset_roads(dest);
9769 send_ruleset_goods(dest);
9771 send_ruleset_styles(dest);
9773 send_ruleset_cities(dest);
9775 send_ruleset_musics(dest);
9776 send_ruleset_cache(dest);
9777
9778 /* Indicate client that all rulesets have now been sent. */
9780
9781 /* changed game settings will be send in
9782 * connecthand.c:establish_new_connection() */
9783
9785}
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:900
#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:890
#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:891
#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 RS_DEFAULT_HP
Definition game.h:886
#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:892
#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_HP
Definition game.h:887
#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_MAX_HP
Definition game.h:888
#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:369
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:329
const char * ruler_title_female_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:387
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:378
void governments_alloc(int num)
Definition government.c:533
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:318
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:959
#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:2642
void playercolor_free(void)
Definition plrhand.c:3342
void playercolor_init(void)
Definition plrhand.c:3333
int playercolor_count(void)
Definition plrhand.c:3381
void playercolor_add(struct rgbcolor *prgbcolor)
Definition plrhand.c:3361
void count_playable_nations(void)
Definition plrhand.c:2599
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:427
static void ruleset_load_traits(struct trait_limits *out, struct section_file *file, const char *secname, const char *field_prefix)
Definition ruleset.c:1317
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:9457
#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:1218
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:1993
static bool load_terrain_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2864
static bool load_style_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5764
int ruleset_purge_unused_entities(void)
Definition ruleset.c:317
#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:4469
#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:8304
#define section_strlcpy(dst, src)
Definition ruleset.c:121
static bool load_action_range(struct section_file *file, action_id act)
Definition ruleset.c:6493
#define check_name(name)
Definition ruleset.c:115
static void send_ruleset_units(struct conn_list *dest)
Definition ruleset.c:8119
static void send_ruleset_governments(struct conn_list *dest)
Definition ruleset.c:8984
static bool load_action_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1486
static struct extra_type * lookup_resource(const char *filename, const char *name, const char *jsection)
Definition ruleset.c:1197
static struct section_file * openload_luadata_file(const char *rsdir)
Definition ruleset.c:630
static bool load_ruleset_techs(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1624
static bool purge_unused_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleset.c:331
void rulesets_deinit(void)
Definition ruleset.c:9447
static bool load_action_ui_name(struct section_file *file, int act, const char *entry_name, const char *compat_name)
Definition ruleset.c:6430
static void send_ruleset_resources(struct conn_list *dest)
Definition ruleset.c:8589
static bool load_ruleset_buildings(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2736
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:1049
static void nullcheck_secfile_destroy(struct section_file *file)
Definition ruleset.c:9436
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:6392
static void send_ruleset_clauses(struct conn_list *dest)
Definition ruleset.c:9156
static void send_ruleset_game(struct conn_list *dest)
Definition ruleset.c:9276
char * parser_buffer
Definition ruleset.c:213
#define NATION_SECTION_PREFIX
Definition ruleset.c:97
static bool load_ruleset_effects(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:6222
static bool lookup_cbonus_list(struct combat_bonus_list *list, struct section_file *file, const char *sec, const char *sub)
Definition ruleset.c:801
static void send_ruleset_nations(struct conn_list *dest)
Definition ruleset.c:9030
static void send_ruleset_roads(struct conn_list *dest)
Definition ruleset.c:8746
static int ruleset_purge_unused_enablers(void)
Definition ruleset.c:248
#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:4861
static void send_ruleset_tech_classes(struct conn_list *dest)
Definition ruleset.c:8286
static void send_ruleset_action_enablers(struct conn_list *dest)
Definition ruleset.c:8899
static void send_ruleset_control(struct conn_list *dest)
Definition ruleset.c:4667
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:9367
#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:219
#define TERRAIN_SECTION_PREFIX
Definition ruleset.c:106
static struct section_file * openload_ruleset_file(const char *whichset, const char *rsdir)
Definition ruleset.c:575
static void send_ruleset_musics(struct conn_list *dest)
Definition ruleset.c:9250
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:1268
int ruleset_purge_redundant_reqs(void)
Definition ruleset.c:494
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:8786
static const char name_too_long[]
Definition ruleset.c:119
bool reload_rulesets_settings(void)
Definition ruleset.c:9714
static struct strvec * lookup_strvec(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleset.c:1177
#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:860
static bool load_game_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1356
static void send_ruleset_counters(struct conn_list *dest)
Definition ruleset.c:8395
static void send_ruleset_specialists(struct conn_list *dest)
Definition ruleset.c:8258
#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:8927
static bool load_government_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:4387
static int char * script_buffer
Definition ruleset.c:212
static void send_ruleset_team_names(struct conn_list *dest)
Definition ruleset.c:9337
static void send_ruleset_cities(struct conn_list *dest)
Definition ruleset.c:9222
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:892
static bool purge_redundant_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleset.c:416
static char * lookup_string(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleset.c:1157
static const char * check_leader_names(struct nation_type *pnation)
Definition ruleset.c:4705
#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:465
static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir, char **buffer, bool optional)
Definition ruleset.c:603
char * get_parser_buffer(void)
Definition ruleset.c:566
static bool load_building_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2655
#define EXTRA_SECTION_PREFIX
Definition ruleset.c:100
void send_rulesets(struct conn_list *dest)
Definition ruleset.c:9737
#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:925
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:6004
static bool load_ruleset_styles(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5825
static struct government * lookup_government(struct section_file *file, const char *entry, const char *filename, struct government *fallback)
Definition ruleset.c:1132
static bool load_ruleset_units(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2114
static bool load_action_blocked_by_list(struct section_file *file, const char *filename, struct action *paction)
Definition ruleset.c:6558
static void send_ruleset_styles(struct conn_list *dest)
Definition ruleset.c:9140
#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:658
static void send_ruleset_disasters(struct conn_list *dest)
Definition ruleset.c:8818
static bool purge_duplicate_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleset.c:371
static bool lookup_tech_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleset.c:985
#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:6673
static bool load_nation_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:4725
static void send_ruleset_achievements(struct conn_list *dest)
Definition ruleset.c:8848
#define SCRIPT_SUFFIX
Definition ruleset.c:85
static void send_ruleset_bases(struct conn_list *dest)
Definition ruleset.c:8724
static bool load_ruleset_terrain(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:3200
static int ruleset_purge_unused_effects(void)
Definition ruleset.c:294
static bool load_action_actor_consuming_always(struct section_file *file, action_id act)
Definition ruleset.c:6541
static bool load_action_post_success_force(struct section_file *file, const char *filename, int performer_slot, struct action *paction)
Definition ruleset.c:6602
static bool load_tech_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1506
#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:6518
static void send_ruleset_multipliers(struct conn_list *dest)
Definition ruleset.c:9188
char * get_script_buffer(void)
Definition ruleset.c:558
static void send_ruleset_actions(struct conn_list *dest)
Definition ruleset.c:8869
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:4877
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:5903
static bool load_ruleset_nations(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5047
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:5946
static void send_ruleset_unit_classes(struct conn_list *dest)
Definition ruleset.c:8071
#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:1101
static void send_ruleset_extras(struct conn_list *dest)
Definition ruleset.c:8608
#define rs_sanity_veteran(_path, _entry, _i, _condition, _action)
static void send_ruleset_terrain(struct conn_list *dest)
Definition ruleset.c:8482
#define GOVERNMENT_SECTION_PREFIX
Definition ruleset.c:94
static bool load_unit_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1835
static void send_ruleset_trade_routes(struct conn_list *dest)
Definition ruleset.c:8963
static bool load_ruleset_actions(struct section_file *file, struct section_file *gamefile, struct rscompat_info *compat)
Definition ruleset.c:7741
static void notify_ruleset_fallback(const char *msg)
Definition ruleset.c:9359
static bool lookup_bv_actions(struct section_file *file, const char *filename, bv_actions *target, const char *path)
Definition ruleset.c:6639
static void send_ruleset_buildings(struct conn_list *dest)
Definition ruleset.c:8416
#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:1294
#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:513
static bool load_action_range_max(struct section_file *file, action_id act)
Definition ruleset.c:6452
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:5982
#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:2466
void update_nations_with_startpos(void)
Definition srv_main.c:2271
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_target type
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char helptext[MAX_LEN_PACKET]
enum counter_behavior behavior
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:169
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