Freeciv-3.3
Loading...
Searching...
No Matches
ruleload.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdarg.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23/* utility */
24#include "bitvector.h"
25#include "deprecations.h"
26#include "fcintl.h"
27#include "log.h"
28#include "mem.h"
29#include "registry.h"
30#include "shared.h"
31#include "string_vector.h"
32#include "support.h"
33
34/* common */
35#include "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 "ruleload.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 ENABLER_SECTION_PREFIX "enabler_"
112#define ACTION_ENABLER_SECTION_PREFIX "actionenabler_"
113#define ACTION_SECTION_PREFIX "action_"
114#define MULTIPLIER_SECTION_PREFIX "multiplier_"
115#define COUNTER_SECTION_PREFIX "counter_"
116
117#define check_name(name) (check_strlen(name, MAX_LEN_NAME, NULL))
118#define check_cityname(name) (check_strlen(name, MAX_LEN_CITYNAME, NULL))
119
120/* avoid re-reading files */
121static const char name_too_long[] = "Name \"%s\" too long; truncating.";
122#define MAX_SECTION_LABEL 64
123#define section_strlcpy(dst, src) \
124 (void) loud_strlcpy(dst, src, MAX_SECTION_LABEL, name_too_long)
125static char *resource_sections = NULL;
126static char *terrain_sections = NULL;
127static char *extra_sections = NULL;
128static char *base_sections = NULL;
129static char *road_sections = NULL;
130
132
133static bool load_rulesetdir(const char *rsdir, bool compat_mode,
135 bool act, bool buffer_script, bool load_luadata);
136static struct section_file *openload_ruleset_file(const char *whichset,
137 const char *rsdir);
138
139static bool load_game_names(struct section_file *file,
140 struct rscompat_info *compat);
141static bool load_action_names(struct section_file *file,
142 struct rscompat_info *compat);
143static bool load_tech_names(struct section_file *file,
144 struct rscompat_info *compat);
145static bool load_unit_names(struct section_file *file,
146 struct rscompat_info *compat);
147static bool load_building_names(struct section_file *file,
148 struct rscompat_info *compat);
149static bool load_government_names(struct section_file *file,
150 struct rscompat_info *compat);
151static bool load_terrain_names(struct section_file *file,
152 struct rscompat_info *compat);
153static bool load_style_names(struct section_file *file,
154 struct rscompat_info *compat);
155static bool load_nation_names(struct section_file *file,
156 struct rscompat_info *compat);
157static bool load_city_name_list(struct section_file *file,
158 struct nation_type *pnation,
159 const char *secfile_str1,
160 const char *secfile_str2,
161 const char **allowed_terrains,
162 size_t atcount);
163
164static bool load_ruleset_techs(struct section_file *file,
165 struct rscompat_info *compat);
166static bool load_ruleset_units(struct section_file *file,
167 struct rscompat_info *compat);
168static bool load_ruleset_buildings(struct section_file *file,
169 struct rscompat_info *compat);
170static bool load_ruleset_governments(struct section_file *file,
171 struct rscompat_info *compat);
172static bool load_ruleset_terrain(struct section_file *file,
173 struct rscompat_info *compat);
174static bool load_ruleset_styles(struct section_file *file,
175 struct rscompat_info *compat);
176static bool load_ruleset_cities(struct section_file *file,
177 struct rscompat_info *compat);
178static bool load_ruleset_effects(struct section_file *file,
179 struct rscompat_info *compat);
180static bool load_ruleset_game(struct section_file *file, bool act,
181 struct rscompat_info *compat);
182static bool load_ruleset_actions(struct section_file *file,
183 struct section_file *gamefile,
184 struct rscompat_info *compat);
185
186static void send_ruleset_tech_classes(struct conn_list *dest);
187static void send_ruleset_techs(struct conn_list *dest);
188static void send_ruleset_unit_classes(struct conn_list *dest);
189static void send_ruleset_units(struct conn_list *dest);
190static void send_ruleset_buildings(struct conn_list *dest);
191static void send_ruleset_terrain(struct conn_list *dest);
192static void send_ruleset_resources(struct conn_list *dest);
193static void send_ruleset_extras(struct conn_list *dest);
194static void send_ruleset_bases(struct conn_list *dest);
195static void send_ruleset_roads(struct conn_list *dest);
196static void send_ruleset_goods(struct conn_list *dest);
197static void send_ruleset_governments(struct conn_list *dest);
198static void send_ruleset_styles(struct conn_list *dest);
199static void send_ruleset_clauses(struct conn_list *dest);
200static void send_ruleset_musics(struct conn_list *dest);
201static void send_ruleset_cities(struct conn_list *dest);
202static void send_ruleset_game(struct conn_list *dest);
203static void send_ruleset_team_names(struct conn_list *dest);
204
205static bool load_ruleset_veteran(struct section_file *file,
206 const char *path,
207 struct veteran_system **vsystem, char *err,
208 size_t err_len);
209
212
213/**********************************************************************/
218 const char *file, const char *function,
219 int line, enum log_level level,
220 const char *format, ...)
221{
222 va_list args;
223 char buf[MAX_LEN_LOG_LINE];
224
225 if (logger == NULL && !log_do_output_for_level(level)) {
226 return;
227 }
228
229 va_start(args, format);
230 if (logger != NULL) {
231 fc_vsnprintf(buf, sizeof(buf), format, args);
232 logger(buf);
233 } else {
234 vdo_log(file, function, line, FALSE, level, buf, sizeof(buf), format, args);
235 }
236 va_end(args);
237
238 if (LOG_FATAL >= level) {
240 }
241}
242
243/**********************************************************************/
247{
248 int purged = 0;
249
250 action_iterate(act_id) {
251 struct action *paction = action_by_number(act_id);
252
254 == 0) {
255 /* Not relevant. */
256 continue;
257 }
258
259 /* Impossible hard requirement. */
261 /* Make sure that all action enablers are disabled. */
263 ae) {
264 ae->rulesave.ruledit_disabled = TRUE;
265 purged++;
267
268 log_normal("Purged all action enablers for %s",
270 }
271
272 /* Impossible requirement vector requirement. */
274 ae) {
275 if (!ae->rulesave.ruledit_disabled
277 || req_vec_is_impossible_to_fulfill(&ae->target_reqs))) {
278 ae->rulesave.ruledit_disabled = TRUE;
279 purged++;
280 log_normal("Purged unused action enabler for %s",
282 }
285
286 return purged;
287}
288
289/**********************************************************************/
293{
294 int purged = 0;
295 enum effect_type type;
296
301 eft->rulesave.do_not_save = TRUE;
302 purged++;
303 log_normal("Purged unused effect for %s",
304 effect_type_name(eft->type));
305 }
307 }
308
309 return purged;
310}
311
312/**********************************************************************/
316{
317 int purged = 0;
318
321
322 return purged;
323}
324
325/**********************************************************************/
330 const char *msg)
331{
332 struct req_vec_problem *problem;
333 bool result;
334
336 reqs);
337
338 if (problem == NULL) {
339 /* No problem. */
340 return FALSE;
341 }
342
343 if (problem->num_suggested_solutions == 0) {
344 /* No solution. */
346 return FALSE;
347 }
348
349 if (problem->num_suggested_solutions == 1
350 && problem->suggested_solutions[0].operation == RVCO_REMOVE) {
351 /* Remove !present req that never is there. */
352 log_normal("%s", msg);
353 result = req_vec_change_apply(&problem->suggested_solutions[0],
356 return result;
357 }
358
359 /* Not handled. Don't know what this is. */
360 fc_assert(problem->num_suggested_solutions == 1);
362 return FALSE;
363}
364
365/**********************************************************************/
370 const char *msg)
371{
372 struct req_vec_problem *problem;
373 bool result;
374
376 reqs);
377
378 if (problem == NULL) {
379 /* No problem. */
380 return FALSE;
381 }
382
383 if (problem->num_suggested_solutions == 0) {
384 /* No solution. */
386 return FALSE;
387 }
388
389 if (problem->num_suggested_solutions == 2
390 && problem->suggested_solutions[0].operation == RVCO_REMOVE
391 && problem->suggested_solutions[1].operation == RVCO_REMOVE
392 && are_requirements_equal(&problem->suggested_solutions[0].req,
393 &problem->suggested_solutions[1].req)) {
394 /* Simple duplication is handled. */
395 log_normal("%s", msg);
396 result = req_vec_change_apply(&problem->suggested_solutions[1],
399 return result;
400 }
401
402 /* Requirements of different kinds making each other redundant isn't
403 * supported yet. It could be done by always removing the most general
404 * requirement. So unit type is kept when redundant with unit flag, unit
405 * class and unit class flag etc. */
407 return FALSE;
408}
409
410/**********************************************************************/
415 const char *msg)
416{
417 return (purge_unused_req_vec(reqs, msg)
419}
420
421/**********************************************************************/
426{
427 int purged = 0;
428
429 action_iterate(act_id) {
430 struct action *paction = action_by_number(act_id);
431 char actor_reqs[MAX_LEN_NAME * 2];
432 char target_reqs[MAX_LEN_NAME * 2];
433
434 /* Error log text */
435 fc_snprintf(actor_reqs, sizeof(actor_reqs),
436 "Purged redundant requirement in"
437 " %s in action enabler for %s",
438 "actor_reqs", action_rule_name(paction));
439 fc_snprintf(target_reqs, sizeof(target_reqs),
440 "Purged redundant requirement in"
441 " %s in action enabler for %s",
442 "target_reqs", action_rule_name(paction));
443
444 /* Do the purging. */
446 ae) {
447 while (!ae->rulesave.ruledit_disabled
448 && (purge_redundant_req_vec(&ae->actor_reqs, actor_reqs)
449 || purge_redundant_req_vec(&ae->target_reqs,
450 target_reqs))) {
451 purged++;
452 }
455
456 return purged;
457}
458
459/**********************************************************************/
464{
465 int purged = 0;
466 enum effect_type type;
467
470 char msg[MAX_LEN_NAME * 2];
471
472 /* Error log text */
473 fc_snprintf(msg, sizeof(msg),
474 "Purged redundant requirement in effect of type %s",
476
477 /* Do the purging. */
479 while (purge_redundant_req_vec(&eft->reqs, msg)) {
480 purged++;
481 }
483 }
484
485 return purged;
486}
487
488/**********************************************************************/
493{
494 int purged = 0;
495
498
499 if (purged > 0) {
500 /* An unused requirement may be an obligatory hard requirement. */
502 }
503
504 return purged;
505}
506
507/**********************************************************************/
511static const char *valid_ruleset_filename(const char *subdir,
512 const char *name,
513 const char *extension,
514 bool optional)
515{
516 char filename[512];
517 const char *dfilename;
518
520
521 fc_snprintf(filename, sizeof(filename), "%s" DIR_SEPARATOR "%s.%s",
523 log_verbose("Trying \"%s\".", filename);
524 dfilename = fileinfoname(get_data_dirs(), filename);
525 if (dfilename) {
526 return dfilename;
527 }
528
529 fc_snprintf(filename, sizeof(filename), "default" DIR_SEPARATOR "%s.%s", name, extension);
530 log_verbose("Trying \"%s\": default ruleset directory.", filename);
531 dfilename = fileinfoname(get_data_dirs(), filename);
532 if (dfilename) {
533 return dfilename;
534 }
535
536 fc_snprintf(filename, sizeof(filename), "%s_%s.%s",
538 log_verbose("Trying \"%s\": alternative ruleset filename syntax.",
539 filename);
540 dfilename = fileinfoname(get_data_dirs(), filename);
541 if (dfilename) {
542 return dfilename;
543 } else if (!optional) {
545 /* TRANS: message about an installation error. */
546 _("Could not find a readable \"%s.%s\" ruleset file."),
547 name, extension);
548 }
549
550 return NULL;
551}
552
553/**********************************************************************/
557{
558 return script_buffer;
559}
560
561/**********************************************************************/
565{
566 return parser_buffer;
567}
568
569/**********************************************************************/
573static struct section_file *openload_ruleset_file(const char *whichset,
574 const char *rsdir)
575{
576 char sfilename[512];
579 struct section_file *secfile;
580
581 if (dfilename == NULL) {
582 return NULL;
583 }
584
585 /* Need to save a copy of the filename for following message, since
586 section_file_load() may call datafilename() for includes. */
588 secfile = secfile_load(sfilename, FALSE);
589
590 if (secfile == NULL) {
591 ruleset_error(NULL, LOG_ERROR, "Could not load ruleset '%s':\n%s",
593 }
594
595 return secfile;
596}
597
598/**********************************************************************/
601static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir,
602 char **buffer, bool optional)
603{
606
607 if (dfilename == NULL) {
608 return optional ? TRI_MAYBE : TRI_NO;
609 }
610
611 if (buffer == NULL) {
613 ruleset_error(NULL, LOG_ERROR, "\"%s\": could not load ruleset script.",
614 dfilename);
615
616 return TRI_NO;
617 }
618 } else {
620 }
621
622 return TRI_YES;
623}
624
625/**********************************************************************/
628static struct section_file *openload_luadata_file(const char *rsdir)
629{
630 struct section_file *secfile;
631 char sfilename[512];
632 const char *dfilename = valid_ruleset_filename(rsdir, "luadata",
633 "txt", TRUE);
634
635 if (dfilename == NULL) {
636 return NULL;
637 }
638
639 /* Need to save a copy of the filename for following message, since
640 section_file_load() may call datafilename() for includes. */
642 secfile = secfile_load(sfilename, FALSE);
643
644 if (secfile == NULL) {
645 ruleset_error(NULL, LOG_ERROR, "Could not load luadata '%s':\n%s",
647 }
648
649 return secfile;
650}
651
652/**********************************************************************/
657 struct rscompat_info *compat,
658 const char *sec,
659 const char *sub,
660 const char *rfor)
661{
662 const char *type, *name;
663 int j;
664 const char *filename;
665
666 filename = secfile_name(file);
667
669
670 for (j = 0; (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
671 sec, sub, j)); j++) {
672 char buf[MAX_LEN_NAME];
673 const char *range;
674 bool survives, present, quiet;
675 struct entry *pentry;
676 struct requirement req;
677
678 if (!(pentry = secfile_entry_lookup(file, "%s.%s%d.name",
679 sec, sub, j))) {
681
682 return NULL;
683 }
684 name = NULL;
685 switch (entry_type_get(pentry)) {
686 case ENTRY_BOOL:
687 {
688 bool val;
689
690 if (entry_bool_get(pentry, &val)) {
691 fc_snprintf(buf, sizeof(buf), "%d", val);
692 name = buf;
693 }
694 }
695 break;
696 case ENTRY_INT:
697 {
698 int val;
699
700 if (entry_int_get(pentry, &val)) {
701 fc_snprintf(buf, sizeof(buf), "%d", val);
702 name = buf;
703 }
704 }
705 break;
706 case ENTRY_STR:
708 break;
709 case ENTRY_FLOAT:
712 "\"%s\": trying to have an floating point entry as a requirement name in '%s.%s%d'.",
713 filename, sec, sub, j);
714 break;
717 break;
720 break;
721 case ENTRY_ILLEGAL:
723 break;
724 }
725 if (NULL == name) {
727 "\"%s\": error in handling requirement name for '%s.%s%d'.",
728 filename, sec, sub, j);
729 return NULL;
730 }
731
732 if (!(range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j))) {
734
735 return NULL;
736 }
737
738 survives = FALSE;
739 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.survives",
740 sec, sub, j))
743 "\"%s\": invalid boolean value for survives for "
744 "'%s.%s%d'.", filename, sec, sub, j);
745 }
746
747 present = TRUE;
748 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.present",
749 sec, sub, j))
752 "\"%s\": invalid boolean value for present for "
753 "'%s.%s%d'.", filename, sec, sub, j);
754 }
755 quiet = FALSE;
756 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.quiet",
757 sec, sub, j))
758 && !entry_bool_get(pentry, &quiet)) {
760 "\"%s\": invalid boolean value for quiet for "
761 "'%s.%s%d'.", filename, sec, sub, j);
762 }
763
764 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
766 }
767
769 if (req.source.kind == universals_n_invalid()) {
771 "\"%s\" [%s] has invalid or unknown req: "
772 "\"%s\" \"%s\".",
773 filename, sec, type, name);
774
775 return NULL;
776 }
777
779 }
780
781 return &reqs_list;
782}
783
784/**********************************************************************/
788 struct section_file *file,
789 const char *sec,
790 const char *sub)
791{
792 const char *flag;
793 int j;
794 const char *filename;
795 bool success = TRUE;
796
797 filename = secfile_name(file);
798
799 for (j = 0; (flag = secfile_lookup_str_default(file, NULL, "%s.%s%d.flag",
800 sec, sub, j)); j++) {
801 struct combat_bonus *bonus = fc_malloc(sizeof(*bonus));
802 const char *type;
803
805 if (!unit_type_flag_id_is_valid(bonus->flag)) {
806 log_error("\"%s\": unknown flag name \"%s\" in '%s.%s'.",
807 filename, flag, sec, sub);
808 FC_FREE(bonus);
809 success = FALSE;
810 continue;
811 }
812 type = secfile_lookup_str(file, "%s.%s%d.type", sec, sub, j);
814 if (!combat_bonus_type_is_valid(bonus->type)) {
815 log_error("\"%s\": unknown bonus type \"%s\" in '%s.%s'.",
816 filename, type, sec, sub);
817 FC_FREE(bonus);
818 success = FALSE;
819 continue;
820 }
821 if (!secfile_lookup_int(file, &bonus->value, "%s.%s%d.value",
822 sec, sub, j)) {
823 log_error("\"%s\": failed to get value from '%s.%s%d'.",
824 filename, sec, sub, j);
825 FC_FREE(bonus);
826 success = FALSE;
827 continue;
828 }
830 "%s.%s%d.quiet",
831 sec, sub, j);
833 }
834
835 return success;
836}
837
838/**********************************************************************/
846static bool lookup_tech(struct section_file *file,
847 struct advance **result,
848 const char *prefix, const char *entry,
849 const char *filename,
850 const char *description)
851{
852 const char *sval;
853
854 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
855 if (!sval || !strcmp(sval, "Never")) {
856 *result = A_NEVER;
857 } else {
858 *result = advance_by_rule_name(sval);
859
860 if (A_NEVER == *result) {
862 "\"%s\" %s %s: couldn't match \"%s\".",
863 filename, (description ? description : prefix), entry, sval);
864 return FALSE;
865 }
866 }
867
868 return TRUE;
869}
870
871/**********************************************************************/
878static bool lookup_unit_list(struct section_file *file, const char *prefix,
879 const char *entry,
880 struct unit_type **output,
881 const char *filename)
882{
883 const char **slist;
884 size_t nval;
885 int i;
886 bool ok = TRUE;
887
888 /* pre-fill with NULL: */
889 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
890 output[i] = NULL;
891 }
892 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
893 if (nval == 0) {
894 /* 'No vector' is considered same as empty vector */
895 if (slist != NULL) {
896 free(slist);
897 }
898 return TRUE;
899 }
900 if (nval > MAX_NUM_UNIT_LIST) {
902 "\"%s\": string vector %s.%s too long (%d, max %d)",
903 filename, prefix, entry, (int) nval, MAX_NUM_UNIT_LIST);
904 ok = FALSE;
905 } else if (nval == 1 && strcmp(slist[0], "") == 0) {
906 free(slist);
907 return TRUE;
908 }
909 if (ok) {
910 for (i = 0; i < nval; i++) {
911 const char *sval = slist[i];
913
914 if (!punittype) {
916 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
917 filename, prefix, entry, i, sval);
918 ok = FALSE;
919 break;
920 }
921 output[i] = punittype;
922 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
924 }
925 }
926 free(slist);
927
928 return ok;
929}
930
931/**********************************************************************/
938static bool lookup_tech_list(struct section_file *file, const char *prefix,
939 const char *entry, int *output,
940 const char *filename)
941{
942 const char **slist;
943 size_t nval;
944 int i;
945 bool ok = TRUE;
946
947 /* pre-fill with A_LAST: */
948 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
949 output[i] = A_LAST;
950 }
951 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
952 if (slist == NULL || nval == 0) {
953 return TRUE;
954 } else if (nval > MAX_NUM_TECH_LIST) {
956 "\"%s\": string vector %s.%s too long (%d, max %d)",
957 filename, prefix, entry, (int) nval, MAX_NUM_TECH_LIST);
958 ok = FALSE;
959 }
960
961 if (ok) {
962 if (nval == 1 && strcmp(slist[0], "") == 0) {
963 FC_FREE(slist);
964 return TRUE;
965 }
966 for (i = 0; i < nval && ok; i++) {
967 const char *sval = slist[i];
969
970 if (NULL == padvance) {
972 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
973 filename, prefix, entry, i, sval);
974 ok = FALSE;
975 }
976 if (!valid_advance(padvance)) {
978 "\"%s\" %s.%s (%d): \"%s\" is removed.",
979 filename, prefix, entry, i, sval);
980 ok = FALSE;
981 }
982
983 if (ok) {
984 output[i] = advance_number(padvance);
985 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
987 }
988 }
989 }
990 FC_FREE(slist);
991
992 return ok;
993}
994
995/**********************************************************************/
1002static bool lookup_building_list(struct section_file *file,
1003 const char *prefix, const char *entry,
1004 int *output, const char *filename)
1005{
1006 const char **slist;
1007 size_t nval;
1008 int i;
1009 bool ok = TRUE;
1010
1011 /* pre-fill with B_LAST: */
1012 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
1013 output[i] = B_LAST;
1014 }
1015 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
1018 "\"%s\": string vector %s.%s too long (%d, max %d)",
1019 filename, prefix, entry, (int) nval, MAX_NUM_BUILDING_LIST);
1020 ok = FALSE;
1021 } else if (nval == 0 || (nval == 1 && strcmp(slist[0], "") == 0)) {
1022 if (slist != NULL) {
1023 FC_FREE(slist);
1024 }
1025 return TRUE;
1026 }
1027 if (ok) {
1028 for (i = 0; i < nval; i++) {
1029 const char *sval = slist[i];
1030 struct impr_type *pimprove = improvement_by_rule_name(sval);
1031
1032 if (NULL == pimprove) {
1034 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1035 filename, prefix, entry, i, sval);
1036 ok = FALSE;
1037 break;
1038 }
1039 output[i] = improvement_number(pimprove);
1040 log_debug("%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
1041 }
1042 }
1043 free(slist);
1044
1045 return ok;
1046}
1047
1048/**********************************************************************/
1054static bool lookup_unit_type(struct section_file *file,
1055 const char *prefix,
1056 const char *entry,
1057 const struct unit_type **result,
1058 const char *filename,
1059 const char *description)
1060{
1061 const char *sval;
1062
1063 sval = secfile_lookup_str_default(file, "None", "%s.%s", prefix, entry);
1064
1065 if (strcmp(sval, "None") == 0) {
1066 *result = NULL;
1067 } else {
1068 *result = unit_type_by_rule_name(sval);
1069 if (*result == NULL) {
1071 "\"%s\" %s %s: couldn't match \"%s\".",
1072 filename, (description ? description : prefix), entry, sval);
1073
1074 return FALSE;
1075 }
1076 }
1077
1078 return TRUE;
1079}
1080
1081/**********************************************************************/
1085static struct government *lookup_government(struct section_file *file,
1086 const char *entry,
1087 const char *filename,
1088 struct government *fallback)
1089{
1090 const char *sval;
1091 struct government *gov;
1092
1093 sval = secfile_lookup_str_default(file, NULL, "%s", entry);
1094 if (!sval) {
1095 gov = fallback;
1096 } else {
1098 }
1099 if (!gov) {
1101 "\"%s\" %s: couldn't match \"%s\".",
1102 filename, entry, sval);
1103 }
1104 return gov;
1105}
1106
1107/**********************************************************************/
1110static char *lookup_string(struct section_file *file, const char *prefix,
1111 const char *suffix)
1112{
1113 const char *sval = secfile_lookup_str(file, "%s.%s", prefix, suffix);
1114
1115 if (NULL != sval) {
1116 char copy[strlen(sval) + 1];
1117
1118 strcpy(copy, sval);
1120 if (strlen(copy) > 0) {
1121 return fc_strdup(copy);
1122 }
1123 }
1124 return NULL;
1125}
1126
1127/**********************************************************************/
1130static struct strvec *lookup_strvec(struct section_file *file,
1131 const char *prefix, const char *suffix)
1132{
1133 size_t dim;
1134 const char **vec = secfile_lookup_str_vec(file, &dim,
1135 "%s.%s", prefix, suffix);
1136
1137 if (NULL != vec) {
1138 struct strvec *dest = strvec_new();
1139
1140 strvec_store(dest, vec, dim);
1141 free(vec);
1142 return dest;
1143 }
1144 return NULL;
1145}
1146
1147/**********************************************************************/
1150static struct extra_type *lookup_resource(const char *filename,
1151 const char *name,
1152 const char *jsection)
1153{
1154 struct extra_type *pres;
1155
1157
1158 if (pres == NULL) {
1160 "\"%s\" [%s] has unknown \"%s\".",
1161 filename, jsection, name);
1162 }
1163
1164 return pres;
1165}
1166
1167/**********************************************************************/
1171static bool lookup_terrain(struct section_file *file,
1172 const char *entry,
1173 const char *filename,
1174 struct terrain *pthis,
1175 struct terrain **result,
1176 bool null_acceptable)
1177{
1178 const int j = terrain_index(pthis);
1179 const char *jsection = &terrain_sections[j * MAX_SECTION_LABEL];
1180 const char *name = secfile_lookup_str(file, "%s.%s", jsection, entry);
1181 struct terrain *pterr;
1182
1183 if (NULL == name && !null_acceptable) {
1184 return FALSE;
1185 }
1186
1187 if (NULL == name
1188 || *name == '\0'
1189 || (0 == strcmp(name, "none"))
1190 || (0 == strcmp(name, "no"))) {
1191 *result = T_NONE;
1192
1193 return TRUE;
1194 }
1195 if (0 == strcmp(name, "yes")) {
1196 *result = pthis;
1197
1198 return TRUE;
1199 }
1200
1202 *result = pterr;
1203
1204 if (pterr == NULL) {
1206 "\"%s\" [%s] has unknown \"%s\".",
1207 secfile_name(file), jsection, name);
1208 return FALSE;
1209 }
1210
1211 return TRUE;
1212}
1213
1214/**********************************************************************/
1221static bool lookup_time(const struct section_file *secfile, int *turns,
1222 const char *sec_name, const char *property_name,
1223 const char *filename, const char *item_name,
1224 bool *ok)
1225{
1226 /* Assumes that PACKET_UNIT_INFO.activity_count in packets.def is UINT16 */
1227 const int max_turns = 65535 / ACTIVITY_FACTOR;
1228
1229 if (!secfile_lookup_int(secfile, turns, "%s.%s", sec_name, property_name)) {
1230 return FALSE;
1231 }
1232
1233 if (*turns > max_turns) {
1235 "\"%s\": \"%s\": \"%s\" value %d too large (max %d)",
1236 filename, item_name ? item_name : sec_name,
1237 property_name, *turns, max_turns);
1238 *ok = FALSE;
1239 }
1240
1241 return TRUE; /* we found _something */
1242}
1243
1244/**********************************************************************/
1248 const char *domain,
1249 struct section_file *file,
1250 const char *sec_name)
1251{
1252 const char *name = secfile_lookup_str(file, "%s.name", sec_name);
1253 const char *rule_name = secfile_lookup_str(file, "%s.rule_name", sec_name);
1254
1255 if (!name) {
1257 "\"%s\" [%s]: no \"name\" specified.",
1258 secfile_name(file), sec_name);
1259 return FALSE;
1260 }
1261
1262 names_set(pname, domain, name, rule_name);
1263
1264 return TRUE;
1265}
1266
1267/**********************************************************************/
1271 struct section_file *file,
1272 const char *secname, const char *field_prefix)
1273{
1274 enum trait tr;
1275
1276 /* FIXME: Use specenum trait names without duplicating them here.
1277 * Just needs to take care of case.
1278 * This list is also duplicated in rulesave.c:save_traits() */
1279 const char *trait_names[] = {
1280 "expansionist",
1281 "trader",
1282 "aggressive",
1283 "builder",
1284 NULL
1285 };
1286
1287 for (tr = trait_begin(); tr != trait_end() && trait_names[tr] != NULL; tr = trait_next(tr)) {
1288 out[tr].min = secfile_lookup_int_default(file, -1, "%s.%s%s_min",
1289 secname,
1291 trait_names[tr]);
1292 out[tr].max = secfile_lookup_int_default(file, -1, "%s.%s%s_max",
1293 secname,
1295 trait_names[tr]);
1296 out[tr].fixed = secfile_lookup_int_default(file, -1, "%s.%s%s_default",
1297 secname,
1299 trait_names[tr]);
1300 }
1301
1302 fc_assert(tr == trait_end()); /* number of trait_names correct */
1303}
1304
1305/**********************************************************************/
1309static bool load_game_names(struct section_file *file,
1310 struct rscompat_info *compat)
1311{
1312 struct section_list *sec;
1313 int nval;
1314 const char *filename = secfile_name(file);
1315 bool ok = TRUE;
1316
1317 /* section: datafile */
1319 if (compat->version <= 0) {
1320 return FALSE;
1321 }
1322
1323 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1324 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1325
1327 nval = (NULL != sec ? section_list_size(sec) : 0);
1329 int num = nval; /* No "size_t" to printf */
1330
1332 "\"%s\": Too many achievement types (%d, max %d)",
1333 filename, num, MAX_ACHIEVEMENT_TYPES);
1334 ok = FALSE;
1335 } else {
1337 }
1338
1339 if (ok) {
1342
1343 if (!ruleset_load_names(&pach->name, NULL, file, sec_name)) {
1345 "\"%s\": Cannot load achievement names",
1346 filename);
1347 ok = FALSE;
1348 break;
1349 }
1351 }
1352
1354
1355 if (ok) {
1357
1358 nval = (NULL != sec ? section_list_size(sec) : 0);
1359 if (nval > MAX_GOODS_TYPES) {
1360 int num = nval; /* No "size_t" to printf */
1361
1363 "\"%s\": Too many goods types (%d, max %d)",
1364 filename, num, MAX_GOODS_TYPES);
1366 ok = FALSE;
1367 } else if (nval < 1) {
1369 "\"%s\": At least one goods type needed",
1370 filename);
1372 ok = FALSE;
1373 } else {
1375 }
1376
1377 if (ok) {
1379 const char *sec_name
1381
1382 if (!ruleset_load_names(&pgood->name, NULL, file, sec_name)) {
1384 "\"%s\": Cannot load goods names",
1385 filename);
1386 ok = FALSE;
1387 break;
1388 }
1390 }
1392 }
1393
1394 if (ok) {
1395
1397
1398 nval = (NULL != sec ? section_list_size(sec) : 0);
1399 if (nval > MAX_COUNTERS) {
1400 size_t num = nval;
1401
1403 "\"%s\": Too many counters (" SIZE_T_PRINTF ", max %d)",
1404 filename, num, MAX_COUNTERS);
1405 ok = FALSE;
1406 }
1407
1408 if (ok) {
1409 int count_idx;
1410
1412
1413 for (count_idx = 0; count_idx < nval; count_idx++) {
1414
1416 const char *sec_name
1418
1419 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
1421 "\"%s\": Cannot load counters names",
1422 filename);
1423 ok = FALSE;
1424 break;
1425 }
1426 }
1427 }
1428
1430 }
1431
1432 return ok;
1433}
1434
1435/**********************************************************************/
1439static bool load_action_names(struct section_file *file,
1440 struct rscompat_info *compat)
1441{
1442 const char *filename = secfile_name(file);
1443 bool ok = TRUE;
1444
1445 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1446 return FALSE;
1447 }
1448
1449 (void) secfile_entry_by_path(file, "datafile.description"); /* Unused */
1450 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* Unused */
1451
1452 return ok;
1453}
1454
1455/**********************************************************************/
1459static bool load_tech_names(struct section_file *file,
1460 struct rscompat_info *compat)
1461{
1462 struct section_list *sec = NULL;
1463 /* Number of techs in the ruleset (means without A_NONE). */
1464 int num_techs = 0;
1465 int i;
1466 const char *filename = secfile_name(file);
1467 bool ok = TRUE;
1468 const char *flag;
1469
1470 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1471 return FALSE;
1472 }
1473
1474 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1475 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1476
1477 /* User tech flag names */
1478 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1479 i++) {
1480 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1481 i);
1484 "\"%s\": Duplicate tech flag name '%s'",
1485 filename, flag);
1486 ok = FALSE;
1487 break;
1488 }
1489 if (i > MAX_NUM_USER_TECH_FLAGS) {
1491 "\"%s\": Too many user tech flags!",
1492 filename);
1493 ok = FALSE;
1494 break;
1495 }
1496
1497 set_user_tech_flag_name(TECH_USER_1 + i, flag, helptxt);
1498 }
1499
1500 if (ok) {
1501 size_t nval;
1502
1503 for (; i < MAX_NUM_USER_TECH_FLAGS; i++) {
1505 }
1506
1507 /* Tech classes */
1509
1510 nval = (NULL != sec ? section_list_size(sec) : 0);
1511 if (nval > MAX_NUM_TECH_CLASSES) {
1512 int num = nval; /* No "size_t" to printf */
1513
1515 "\"%s\": Too many tech classes (%d, max %d)",
1516 filename, num, MAX_NUM_TECH_CLASSES);
1518 ok = FALSE;
1519 } else {
1521 }
1522
1523 if (ok) {
1525 const char *sec_name
1527
1528 if (!ruleset_load_names(&ptclass->name, NULL, file, sec_name)) {
1529 ruleset_error(NULL, LOG_ERROR, "\"%s\": Cannot load tech class names",
1530 filename);
1531 ok = FALSE;
1532 break;
1533 }
1535 }
1536 }
1537
1538 if (ok) {
1539 /* The techs: */
1541 if (NULL == sec || 0 == (num_techs = section_list_size(sec))) {
1543 "\"%s\": No Advances?!?", filename);
1544 ok = FALSE;
1545 } else {
1546 log_verbose("%d advances (including possibly unused)", num_techs);
1547 if (num_techs + A_FIRST > A_LAST) {
1549 "\"%s\": Too many advances (%d, max %d)",
1550 filename, num_techs, A_LAST - A_FIRST);
1551 ok = FALSE;
1552 }
1553 }
1554 }
1555
1556 if (ok) {
1557 game.control.num_tech_types = num_techs + A_FIRST; /* includes A_NONE */
1558
1559 i = 0;
1560 advance_iterate(adv) {
1561 if (!ruleset_load_names(&adv->name, NULL, file,
1563 ok = FALSE;
1564 break;
1565 }
1566 i++;
1568 }
1570
1571 return ok;
1572}
1573
1574/**********************************************************************/
1577static bool load_ruleset_techs(struct section_file *file,
1578 struct rscompat_info *compat)
1579{
1580 struct section_list *sec;
1581 const char **slist;
1582 int i;
1583 size_t nval;
1585 const char *filename = secfile_name(file);
1586 bool ok = TRUE;
1587
1589
1590 i = 0;
1592 const char *sec_name = section_name(section_list_get(sec, i));
1593
1594 ptclass->cost_pct = secfile_lookup_int_default(file, 100, "%s.%s",
1595 sec_name, "cost_pct");
1596
1597 i++;
1599
1601
1602 i = 0;
1603 advance_iterate(a) {
1604 const char *sec_name = section_name(section_list_get(sec, i));
1605 const char *sval;
1606 int j, ival;
1607 struct requirement_vector *research_reqs;
1608
1609 if (!lookup_tech(file, &a->require[AR_ONE], sec_name, "req1",
1610 filename, rule_name_get(&a->name))
1611 || !lookup_tech(file, &a->require[AR_TWO], sec_name, "req2",
1612 filename, rule_name_get(&a->name))
1613 || !lookup_tech(file, &a->require[AR_ROOT], sec_name, "root_req",
1614 filename, rule_name_get(&a->name))) {
1615 ok = FALSE;
1616 break;
1617 }
1618
1619 if ((A_NEVER == a->require[AR_ONE] && A_NEVER != a->require[AR_TWO])
1620 || (A_NEVER != a->require[AR_ONE] && A_NEVER == a->require[AR_TWO])) {
1622 "\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
1623 filename, sec_name, rule_name_get(&a->name));
1624 ok = FALSE;
1625 break;
1626 }
1627 if (a_none == a->require[AR_ONE] && a_none != a->require[AR_TWO]) {
1629 "\"%s\" [%s] \"%s\": should have \"None\" second.",
1630 filename, sec_name, rule_name_get(&a->name));
1631 ok = FALSE;
1632 break;
1633 }
1634
1635 if (game.control.num_tech_classes == 0) {
1636 a->tclass = NULL;
1637 } else {
1638 const char *classname;
1639
1640 classname = lookup_string(file, sec_name, "class");
1641 if (classname != NULL) {
1644 if (a->tclass == NULL) {
1646 "\"%s\" [%s] \"%s\": Unknown tech class \"%s\".",
1647 filename, sec_name, rule_name_get(&a->name), classname);
1648 ok = FALSE;
1649 break;
1650 }
1651 } else {
1652 a->tclass = NULL; /* Default */
1653 }
1654 }
1655
1656 research_reqs = lookup_req_list(file, compat, sec_name, "research_reqs",
1657 rule_name_get(&a->name));
1658 if (research_reqs == NULL) {
1659 ok = FALSE;
1660 break;
1661 }
1662
1663 requirement_vector_copy(&a->research_reqs, research_reqs);
1664
1665 BV_CLR_ALL(a->flags);
1666
1667 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
1668 for (j = 0; j < nval; j++) {
1669 sval = slist[j];
1670 if (strcmp(sval, "") == 0) {
1671 continue;
1672 }
1676 "\"%s\" [%s] \"%s\": bad flag name \"%s\".",
1677 filename, sec_name, rule_name_get(&a->name), sval);
1678 ok = FALSE;
1679 break;
1680 } else {
1681 BV_SET(a->flags, ival);
1682 }
1683 }
1684 free(slist);
1685
1686 if (!ok) {
1687 break;
1688 }
1689
1690 sz_strlcpy(a->graphic_str,
1691 secfile_lookup_str_default(file, "-", "%s.graphic", sec_name));
1692 sz_strlcpy(a->graphic_alt,
1694 "%s.graphic_alt", sec_name));
1695
1696 a->helptext = lookup_strvec(file, sec_name, "helptext");
1697 a->bonus_message = lookup_string(file, sec_name, "bonus_message");
1698 a->cost = secfile_lookup_int_default(file, -1, "%s.%s",
1699 sec_name, "cost");
1700 a->num_reqs = 0;
1701
1702 i++;
1704
1705 /* Propagate a root tech up into the tech tree. If a technology
1706 * X has Y has a root tech, then any technology requiring X (in the
1707 * normal way or as a root tech) also has Y as a root tech.
1708 * Later techs may gain a whole set of root techs in this way. The one
1709 * we store in AR_ROOT is a more or less arbitrary one of these,
1710 * also signalling that the set is non-empty; after this, you'll still
1711 * have to walk the tech tree to find them all. */
1712restart:
1713
1714 if (ok) {
1715 advance_iterate(a) {
1716 if (valid_advance(a)
1717 && A_NEVER != a->require[AR_ROOT]) {
1718 bool out_of_order = FALSE;
1719
1720 /* Now find any tech depending on this technology and update its
1721 * root_req. */
1722 advance_iterate(b) {
1723 if (valid_advance(b)
1724 && A_NEVER == b->require[AR_ROOT]
1725 && (a == b->require[AR_ONE] || a == b->require[AR_TWO])) {
1726 b->require[AR_ROOT] = a->require[AR_ROOT];
1727 b->inherited_root_req = TRUE;
1728 if (b < a) {
1730 }
1731 }
1733
1734 if (out_of_order) {
1735 /* HACK: If we just changed the root_tech of a lower-numbered
1736 * technology, we need to go back so that we can propagate the
1737 * root_tech up to that technology's parents... */
1738 goto restart;
1739 }
1740 }
1742
1743 /* Now rename A_NEVER to A_NONE for consistency */
1745 if (A_NEVER == a->require[AR_ROOT]) {
1746 a->require[AR_ROOT] = a_none;
1747 }
1749
1750 /* Some more consistency checking:
1751 Non-removed techs depending on removed techs is too
1752 broken to fix by default, so die.
1753 */
1754 advance_iterate(a) {
1755 if (valid_advance(a)) {
1756 /* We check for recursive tech loops later,
1757 * in build_required_techs_helper. */
1758 if (!valid_advance(a->require[AR_ONE])) {
1760 "\"%s\" tech \"%s\": req1 leads to removed tech.",
1761 filename, advance_rule_name(a));
1762 ok = FALSE;
1763 break;
1764 }
1765 if (!valid_advance(a->require[AR_TWO])) {
1767 "\"%s\" tech \"%s\": req2 leads to removed tech.",
1768 filename, advance_rule_name(a));
1769 ok = FALSE;
1770 break;
1771 }
1772 }
1774 }
1775
1777 if (ok) {
1779 }
1780
1781 return ok;
1782}
1783
1784/**********************************************************************/
1788static bool load_unit_names(struct section_file *file,
1789 struct rscompat_info *compat)
1790{
1791 struct section_list *sec = NULL;
1792 int nval = 0;
1793 int i;
1794 const char *filename = secfile_name(file);
1795 const char *flag;
1796 bool ok = TRUE;
1797
1798 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1799 return FALSE;
1800 }
1801
1802 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1803 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1804
1805 /* User unit flag names */
1806 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1807 i++) {
1808 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1809 i);
1810
1814 "\"%s\": Duplicate unit flag name '%s'",
1815 filename, flag);
1816 ok = FALSE;
1817 break;
1818 }
1819 if (i > MAX_NUM_USER_UNIT_FLAGS) {
1821 "\"%s\": Too many user unit type flags!",
1822 filename);
1823 ok = FALSE;
1824 break;
1825 }
1826
1828 }
1829
1830 if (ok) {
1831 /* Blank the remaining unit type user flags. */
1832 for (; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
1834 }
1835 }
1836
1837 if (ok) {
1838 /* User unit class flag names */
1839 for (i = 0;
1840 (flag = secfile_lookup_str_default(file, NULL,
1841 "control.class_flags%d.name",
1842 i));
1843 i++) {
1844 const char *helptxt = secfile_lookup_str_default(file, NULL,
1845 "control.class_flags%d.helptxt", i);
1846
1850 "\"%s\": Duplicate unit class flag name '%s'",
1851 filename, flag);
1852 ok = FALSE;
1853 break;
1854 }
1857 "\"%s\": Too many user unit class flags!",
1858 filename);
1859 ok = FALSE;
1860 break;
1861 }
1862
1864 }
1865 }
1866
1867 if (ok) {
1868 /* Blank the remaining unit class user flags. */
1869 for (; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
1871 }
1872 }
1873
1874 if (ok) {
1875 /* Unit classes */
1877 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1879 "\"%s\": No unit classes?!?", filename);
1880 ok = FALSE;
1881 } else {
1882 log_verbose("%d unit classes", nval);
1883 if (nval > UCL_LAST) {
1885 "\"%s\": Too many unit classes (%d, max %d)",
1886 filename, nval, UCL_LAST);
1887 ok = FALSE;
1888 }
1889 }
1890 }
1891
1892 if (ok) {
1894
1896 const int pci = uclass_index(punitclass);
1897
1898 if (!ruleset_load_names(&punitclass->name, NULL, file,
1900 ok = FALSE;
1901 break;
1902 }
1904 }
1906 sec = NULL;
1907
1908 /* The names: */
1909 if (ok) {
1911 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1913 "\"%s\": No unit types?!?", filename);
1914 ok = FALSE;
1915 } else {
1916 log_verbose("%d unit types (including possibly unused)", nval);
1917 if (nval > U_LAST) {
1919 "\"%s\": Too many unit types (%d, max %d)",
1920 filename, nval, U_LAST);
1921 ok = FALSE;
1922 }
1923 }
1924 }
1925
1926 if (ok) {
1928
1930 const int utypei = utype_index(punittype);
1931 if (!ruleset_load_names(&punittype->name, NULL, file,
1933 ok = FALSE;
1934 break;
1935 }
1937 }
1939
1940 return ok;
1941}
1942
1943/**********************************************************************/
1946static bool load_ruleset_veteran(struct section_file *file,
1947 const char *path,
1948 struct veteran_system **vsystem, char *err,
1949 size_t err_len)
1950{
1951 const char **vlist_name;
1954 int i;
1955 bool ret = TRUE;
1956
1957 /* The pointer should be uninitialised. */
1958 if (*vsystem != NULL) {
1959 fc_snprintf(err, err_len, "Veteran system is defined?!");
1960 return FALSE;
1961 }
1962
1963 /* Load data. */
1965 "%s.veteran_names", path);
1967 "%s.veteran_power_fact", path);
1969 "%s.veteran_base_raise_chance", path);
1971 "%s.veteran_work_raise_chance",
1972 path);
1974 "%s.veteran_move_bonus", path);
1975
1976 if (count_name > MAX_VET_LEVELS) {
1977 ret = FALSE;
1978 fc_snprintf(err, err_len, "\"%s\": Too many veteran levels (section "
1979 "'%s': %lu, max %d)", secfile_name(file), path,
1980 (long unsigned)count_name, MAX_VET_LEVELS);
1981 } else if (count_name != count_power
1984 || count_name != count_move) {
1985 ret = FALSE;
1986 fc_snprintf(err, err_len, "\"%s\": Different lengths for the veteran "
1987 "settings in section '%s'", secfile_name(file),
1988 path);
1989 } else if (count_name == 0) {
1990 /* Nothing defined. */
1991 *vsystem = NULL;
1992 } else {
1993 /* Generate the veteran system. */
1995
1996#define rs_sanity_veteran(_path, _entry, _i, _condition, _action) \
1997 if (_condition) { \
1998 log_error("Invalid veteran definition '%s.%s[%d]'!", \
1999 _path, _entry, _i); \
2000 log_debug("Failed check: '%s'. Update value: '%s'.", \
2001 #_condition, #_action); \
2002 _action; \
2003 }
2004 for (i = 0; i < count_name; i++) {
2005 /* Some sanity checks. */
2006 rs_sanity_veteran(path, "veteran_power_fact", i,
2007 (vlist_power[i] < 0), vlist_power[i] = 0);
2008 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2009 (vlist_raise[i] < 0), vlist_raise[i] = 0);
2010 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2011 (vlist_wraise[i] < 0), vlist_wraise[i] = 0);
2012 rs_sanity_veteran(path, "veteran_move_bonus", i,
2013 (vlist_move[i] < 0), vlist_move[i] = 0);
2014 if (i == 0) {
2015 /* First element.*/
2016 rs_sanity_veteran(path, "veteran_power_fact", i,
2017 (vlist_power[i] != 100), vlist_power[i] = 100);
2018 } else if (i == count_name - 1) {
2019 /* Last element. */
2020 rs_sanity_veteran(path, "veteran_power_fact", i,
2021 (vlist_power[i] < vlist_power[i - 1]),
2022 vlist_power[i] = vlist_power[i - 1]);
2023 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2024 (vlist_raise[i] != 0), vlist_raise[i] = 0);
2025 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2026 (vlist_wraise[i] != 0), vlist_wraise[i] = 0);
2027 } else {
2028 /* All elements in between. */
2029 rs_sanity_veteran(path, "veteran_power_fact", i,
2030 (vlist_power[i] < vlist_power[i - 1]),
2031 vlist_power[i] = vlist_power[i - 1]);
2032 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2033 (vlist_raise[i] > 100), vlist_raise[i] = 100);
2034 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2035 (vlist_wraise[i] > 100), vlist_wraise[i] = 100);
2036 }
2037
2040 vlist_wraise[i]);
2041 }
2042#undef rs_sanity_veteran
2043 }
2044
2045 if (vlist_name) {
2047 }
2048 if (vlist_power) {
2050 }
2051 if (vlist_raise) {
2053 }
2054 if (vlist_wraise) {
2056 }
2057 if (vlist_move) {
2059 }
2060
2061 return ret;
2062}
2063
2064/**********************************************************************/
2067static bool load_ruleset_units(struct section_file *file,
2068 struct rscompat_info *compat)
2069{
2070 int j, ival;
2071 size_t nval;
2072 struct section_list *sec, *csec;
2073 const char *sval, **slist;
2074 const char *filename = secfile_name(file);
2075 char msg[MAX_LEN_MSG];
2076 bool ok = TRUE;
2077
2078 if (!load_ruleset_veteran(file, "veteran_system", &game.veteran, msg,
2079 sizeof(msg))
2080 || game.veteran == NULL) {
2082 "Error loading the default veteran system: %s",
2083 msg);
2084 ok = FALSE;
2085 }
2086
2088 nval = (NULL != sec ? section_list_size(sec) : 0);
2089
2091 nval = (NULL != csec ? section_list_size(csec) : 0);
2092
2093 if (ok) {
2095 int i = uclass_index(uc);
2096 const char *sec_name = section_name(section_list_get(csec, i));
2097
2098 if (secfile_lookup_int(file, &uc->min_speed, "%s.min_speed", sec_name)) {
2099 uc->min_speed *= SINGLE_MOVE;
2100 } else {
2102 ok = FALSE;
2103 break;
2104 }
2105 if (!secfile_lookup_int(file, &uc->hp_loss_pct,
2106 "%s.hp_loss_pct", sec_name)) {
2108 ok = FALSE;
2109 break;
2110 }
2111
2112 uc->non_native_def_pct = secfile_lookup_int_default(file, 100,
2113 "%s.non_native_def_pct",
2114 sec_name);
2115
2116 BV_CLR_ALL(uc->flags);
2117 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
2118 for (j = 0; j < nval; j++) {
2119 sval = slist[j];
2120 if (strcmp(sval, "") == 0) {
2121 continue;
2122 }
2123
2124 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
2126 }
2127
2130 ok = FALSE;
2134 "\"%s\" unit_class \"%s\": unit_type flag \"%s\"!",
2135 filename, uclass_rule_name(uc), sval);
2136 } else {
2138 "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
2139 filename, uclass_rule_name(uc), sval);
2140 }
2141 break;
2142 } else {
2143 BV_SET(uc->flags, ival);
2144 }
2145 }
2146 free(slist);
2147
2148 uc->helptext = lookup_strvec(file, sec_name, "helptext");
2149
2150 if (!ok) {
2151 break;
2152 }
2154 }
2155
2156 if (ok) {
2157 /* Tech and Gov requirements; per unit veteran system */
2159 const int i = utype_index(u);
2160 const struct section *psection = section_list_get(sec, i);
2161 const char *sec_name = section_name(psection);
2162 struct requirement_vector *reqs;
2163
2164 reqs = lookup_req_list(file, compat, sec_name, "reqs",
2165 utype_rule_name(u));
2166
2167 if (reqs == NULL) {
2168 ok = FALSE;
2169 break;
2170 }
2171
2172 requirement_vector_copy(&u->build_reqs, reqs);
2173
2174 if (!load_ruleset_veteran(file, sec_name, &u->veteran,
2175 msg, sizeof(msg))) {
2177 "Error loading the veteran system: %s",
2178 msg);
2179 ok = FALSE;
2180 break;
2181 }
2182
2183 if (!lookup_unit_type(file, sec_name, "obsolete_by",
2184 &u->obsoleted_by, filename,
2185 rule_name_get(&u->name))
2186 || !lookup_unit_type(file, sec_name, "convert_to",
2187 &u->converted_to, filename,
2188 rule_name_get(&u->name))) {
2189 ok = FALSE;
2190 break;
2191 }
2192 u->convert_time = 1; /* default */
2193 lookup_time(file, &u->convert_time, sec_name, "convert_time",
2194 filename, rule_name_get(&u->name), &ok);
2196 }
2197
2198 if (ok) {
2199 /* main stats: */
2201 const int i = utype_index(u);
2202 struct unit_class *pclass;
2203 const char *sec_name = section_name(section_list_get(sec, i));
2204 const char *str;
2205
2206 sval = secfile_lookup_str(file, "%s.class", sec_name);
2208 if (!pclass) {
2210 "\"%s\" unit_type \"%s\": bad class \"%s\".",
2211 filename, utype_rule_name(u), sval);
2212 ok = FALSE;
2213 break;
2214 }
2215 u->uclass = pclass;
2216
2217 sz_strlcpy(u->sound_move,
2218 secfile_lookup_str_default(file, "-", "%s.sound_move",
2219 sec_name));
2220 sz_strlcpy(u->sound_move_alt,
2221 secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
2222 sec_name));
2223 sz_strlcpy(u->sound_fight,
2224 secfile_lookup_str_default(file, "-", "%s.sound_fight",
2225 sec_name));
2226 sz_strlcpy(u->sound_fight_alt,
2227 secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
2228 sec_name));
2229
2230 if ((str = secfile_lookup_str(file, "%s.graphic", sec_name))) {
2231 sz_strlcpy(u->graphic_str, str);
2232 } else {
2234 ok = FALSE;
2235 break;
2236 }
2237 sz_strlcpy(u->graphic_alt,
2238 secfile_lookup_str_default(file, "-", "%s.graphic_alt",
2239 sec_name));
2240 sz_strlcpy(u->graphic_alt2,
2241 secfile_lookup_str_default(file, "-", "%s.graphic_alt2",
2242 sec_name));
2243
2244 if (!secfile_lookup_int(file, &u->build_cost,
2245 "%s.build_cost", sec_name)
2246 || !secfile_lookup_int(file, &u->pop_cost,
2247 "%s.pop_cost", sec_name)
2248 || !secfile_lookup_int(file, &u->attack_strength,
2249 "%s.attack", sec_name)
2250 || !secfile_lookup_int(file, &u->defense_strength,
2251 "%s.defense", sec_name)
2252 || !secfile_lookup_int(file, &u->move_rate,
2253 "%s.move_rate", sec_name)
2254 || !secfile_lookup_int(file, &u->vision_radius_sq,
2255 "%s.vision_radius_sq", sec_name)
2256 || !secfile_lookup_int(file, &u->transport_capacity,
2257 "%s.transport_cap", sec_name)
2258 || !secfile_lookup_int(file, &u->hp,
2259 "%s.hitpoints", sec_name)
2260 || !secfile_lookup_int(file, &u->firepower,
2261 "%s.firepower", sec_name)
2262 || !secfile_lookup_int(file, &u->fuel,
2263 "%s.fuel", sec_name)
2264 || !secfile_lookup_int(file, &u->happy_cost,
2265 "%s.uk_happy", sec_name)) {
2267 ok = FALSE;
2268 break;
2269 }
2270 u->move_rate *= SINGLE_MOVE;
2271
2272 if (u->firepower <= 0) {
2274 "\"%s\" unit_type \"%s\":"
2275 " firepower is %d,"
2276 " but must be at least 1. "
2277 " If you want no attack ability,"
2278 " set the unit's attack strength to 0.",
2279 filename, utype_rule_name(u), u->firepower);
2280 ok = FALSE;
2281 break;
2282 }
2283
2284 lookup_cbonus_list(u->bonuses, file, sec_name, "bonuses");
2285
2287 u->upkeep[o] = secfile_lookup_int_default(file, 0, "%s.uk_%s",
2288 sec_name,
2291
2292 slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec_name);
2293
2294 BV_CLR_ALL(u->cargo);
2295 for (j = 0; j < nval; j++) {
2296 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2297
2298 if (!uclass) {
2300 "\"%s\" unit_type \"%s\":"
2301 "has unknown unit class %s as cargo.",
2302 filename, utype_rule_name(u), slist[j]);
2303 ok = FALSE;
2304 break;
2305 }
2306
2307 BV_SET(u->cargo, uclass_index(uclass));
2308 }
2309 free(slist);
2310
2311 if (!ok) {
2312 break;
2313 }
2314
2315 slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec_name);
2316 BV_CLR_ALL(u->targets);
2317 for (j = 0; j < nval; j++) {
2318 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2319
2320 if (!uclass) {
2322 "\"%s\" unit_type \"%s\":"
2323 "has unknown unit class %s as target.",
2324 filename, utype_rule_name(u), slist[j]);
2325 ok = FALSE;
2326 break;
2327 }
2328
2329 BV_SET(u->targets, uclass_index(uclass));
2330 }
2331 free(slist);
2332
2333 if (!ok) {
2334 break;
2335 }
2336
2337 slist = secfile_lookup_str_vec(file, &nval, "%s.embarks", sec_name);
2338 BV_CLR_ALL(u->embarks);
2339 for (j = 0; j < nval; j++) {
2340 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2341
2342 if (!uclass) {
2344 "\"%s\" unit_type \"%s\":"
2345 "has unknown unit class %s as embarkable.",
2346 filename, utype_rule_name(u), slist[j]);
2347 ok = FALSE;
2348 break;
2349 }
2350
2351 BV_SET(u->embarks, uclass_index(uclass));
2352 }
2353 free(slist);
2354
2355 if (!ok) {
2356 break;
2357 }
2358
2359 slist = secfile_lookup_str_vec(file, &nval, "%s.disembarks", sec_name);
2360 BV_CLR_ALL(u->disembarks);
2361 for (j = 0; j < nval; j++) {
2362 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2363
2364 if (!uclass) {
2366 "\"%s\" unit_type \"%s\":"
2367 "has unknown unit class %s as disembarkable.",
2368 filename, utype_rule_name(u), slist[j]);
2369 ok = FALSE;
2370 break;
2371 }
2372
2373 BV_SET(u->disembarks, uclass_index(uclass));
2374 }
2375 free(slist);
2376
2377 if (!ok) {
2378 break;
2379 }
2380
2381 /* Set also all classes that are never unreachable as targets,
2382 * embarks, and disembarks. */
2385 BV_SET(u->targets, uclass_index(preachable));
2386 BV_SET(u->embarks, uclass_index(preachable));
2387 BV_SET(u->disembarks, uclass_index(preachable));
2388 }
2390
2391 str = secfile_lookup_str_default(file, "Main", "%s.vision_layer",
2392 sec_name);
2394 if (!vision_layer_is_valid(u->vlayer)) {
2396 "\"%s\" unit_type \"%s\":"
2397 "has unknown vision layer %s.",
2398 filename, utype_rule_name(u), str);
2399 ok = FALSE;
2400 break;
2401 }
2402
2403 u->helptext = lookup_strvec(file, sec_name, "helptext");
2404
2405 u->paratroopers_range = secfile_lookup_int_default(file,
2406 0, "%s.paratroopers_range", sec_name);
2407
2408 u->bombard_rate = secfile_lookup_int_default(file, 0,
2409 "%s.bombard_rate", sec_name);
2410 u->city_slots = secfile_lookup_int_default(file, 0,
2411 "%s.city_slots", sec_name);
2412 u->city_size = secfile_lookup_int_default(file, 1,
2413 "%s.city_size", sec_name);
2414
2416 "%s.tp_defense", sec_name);
2417 u->tp_defense = transp_def_type_by_name(sval, fc_strcasecmp);
2418 if (!transp_def_type_is_valid(u->tp_defense)) {
2420 "\"%s\" unit_type \"%s\":"
2421 " bad tp_defense \"%s\".",
2422 filename, utype_rule_name(u), sval);
2423 ok = FALSE;
2424 break;
2425 }
2427 }
2428
2429 if (ok) {
2430 /* Flags */
2432 const int i = utype_index(u);
2433
2434 BV_CLR_ALL(u->flags);
2436
2437 slist = secfile_lookup_str_vec(file, &nval, "%s.flags",
2439 for (j = 0; j < nval; j++) {
2440 sval = slist[j];
2441 if (0 == strcmp(sval, "")) {
2442 continue;
2443 }
2446 ok = FALSE;
2450 "\"%s\" unit_type \"%s\": unit_class flag!",
2451 filename, utype_rule_name(u));
2452 } else {
2454 "\"%s\" unit_type \"%s\": bad flag name \"%s\".",
2455 filename, utype_rule_name(u), sval);
2456 }
2457 break;
2458 } else {
2459 BV_SET(u->flags, ival);
2460 }
2461 }
2462 free(slist);
2463
2464 if (!ok) {
2465 break;
2466 }
2468 }
2469
2470 /* Roles */
2471 if (ok) {
2473 const int i = utype_index(u);
2474
2475 BV_CLR_ALL(u->roles);
2476
2477 slist = secfile_lookup_str_vec(file, &nval, "%s.roles",
2479 for (j = 0; j < nval; j++) {
2480 sval = slist[j];
2481 if (strcmp(sval, "") == 0) {
2482 continue;
2483 }
2487 "\"%s\" unit_type \"%s\": bad role name \"%s\".",
2488 filename, utype_rule_name(u), sval);
2489 ok = FALSE;
2490 break;
2491 } else {
2492 BV_SET(u->roles, ival - L_FIRST);
2493 }
2495 }
2496 free(slist);
2498 }
2499
2500 if (ok) {
2501 /* Some more consistency checking: */
2504 if (!valid_advance(padv)) {
2506 "\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
2507 filename, utype_rule_name(u),
2509 ok = FALSE;
2510 break;
2511 }
2513
2514 if (!ok) {
2515 break;
2516 }
2518 }
2519
2522
2523 if (ok) {
2525 }
2526
2527 return ok;
2528}
2529
2530/**********************************************************************/
2534static bool load_building_names(struct section_file *file,
2535 struct rscompat_info *compat)
2536{
2537 struct section_list *sec;
2538 int i, nval = 0;
2539 const char *filename = secfile_name(file);
2540 bool ok = TRUE;
2541 const char *flag;
2542
2543 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2544 return FALSE;
2545 }
2546
2547 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2548 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2549
2550 /* The names: */
2552 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2554 "\"%s\": No improvements?!?", filename);
2555 ok = FALSE;
2556 } else {
2557 log_verbose("%d improvement types (including possibly unused)", nval);
2558 if (nval > B_LAST) {
2560 "\"%s\": Too many improvements (%d, max %d)",
2561 filename, nval, B_LAST);
2562 ok = FALSE;
2563 }
2564 }
2565
2566 if (ok) {
2568
2569 for (i = 0; i < nval; i++) {
2570 struct impr_type *b = improvement_by_number(i);
2571
2572 if (!ruleset_load_names(&b->name, NULL, file, section_name(section_list_get(sec, i)))) {
2573 ok = FALSE;
2574 break;
2575 }
2576 }
2577 }
2578
2579 /* User building flag names */
2580 for (i = 0;
2581 (flag = secfile_lookup_str_default(file, NULL,
2582 "control.building_flags%d.name",
2583 i));
2584 i++) {
2585 const char *helptxt = secfile_lookup_str_default(file, NULL,
2586 "control.building_flags%d.helptxt", i);
2587
2589 != impr_flag_id_invalid()) {
2591 "\"%s\": Duplicate building flag name '%s'",
2592 filename, flag);
2593 ok = FALSE;
2594 break;
2595 }
2598 "\"%s\": Too many user building flags!",
2599 filename);
2600 ok = FALSE;
2601 break;
2602 }
2603
2604 set_user_impr_flag_name(IF_USER_FLAG_1 + i, flag, helptxt);
2605 }
2606
2608
2609 return ok;
2610}
2611
2612/**********************************************************************/
2615static bool load_ruleset_buildings(struct section_file *file,
2616 struct rscompat_info *compat)
2617{
2618 struct section_list *sec;
2619 const char *item;
2620 int i, nval;
2621 const char *filename = secfile_name(file);
2622 bool ok = TRUE;
2623
2625 nval = (NULL != sec ? section_list_size(sec) : 0);
2626
2627 for (i = 0; i < nval && ok; i++) {
2628 struct impr_type *b = improvement_by_number(i);
2629 const char *sec_name = section_name(section_list_get(sec, i));
2630 struct requirement_vector *reqs =
2631 lookup_req_list(file, compat, sec_name, "reqs",
2633
2634 if (reqs == NULL) {
2635 ok = FALSE;
2636 break;
2637 } else {
2638 const char *sval, **slist;
2639 int j, ival;
2640 size_t nflags;
2641
2642 item = secfile_lookup_str(file, "%s.genus", sec_name);
2644 if (!impr_genus_id_is_valid(b->genus)) {
2646 "\"%s\" improvement \"%s\": couldn't match "
2647 "genus \"%s\".", filename,
2649 ok = FALSE;
2650 break;
2651 }
2652
2653 slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec_name);
2654 BV_CLR_ALL(b->flags);
2655
2656 for (j = 0; j < nflags; j++) {
2657 sval = slist[j];
2658 if (strcmp(sval, "") == 0) {
2659 continue;
2660 }
2664 "\"%s\" improvement \"%s\": bad flag name \"%s\".",
2665 filename, improvement_rule_name(b), sval);
2666 ok = FALSE;
2667 break;
2668 } else {
2669 BV_SET(b->flags, ival);
2670 }
2671 }
2672 free(slist);
2673
2674 if (!ok) {
2675 break;
2676 }
2677
2679
2680 {
2681 struct requirement_vector *obs_reqs =
2682 lookup_req_list(file, compat, sec_name, "obsolete_by",
2684
2685 if (obs_reqs == NULL) {
2686 ok = FALSE;
2687 break;
2688 } else {
2689 requirement_vector_copy(&b->obsolete_by, obs_reqs);
2690 }
2691 }
2692
2693 if (!secfile_lookup_int(file, &b->build_cost,
2694 "%s.build_cost", sec_name)
2695 || !secfile_lookup_int(file, &b->upkeep,
2696 "%s.upkeep", sec_name)
2697 || !secfile_lookup_int(file, &b->sabotage,
2698 "%s.sabotage", sec_name)) {
2700 ok = FALSE;
2701 break;
2702 }
2703
2706 "%s.graphic", sec_name));
2709 "%s.graphic_alt", sec_name));
2712 "%s.graphic_alt2", sec_name));
2713
2716 "%s.sound", sec_name));
2719 "%s.sound_alt", sec_name));
2722 "%s.sound_alt2", sec_name));
2723 b->helptext = lookup_strvec(file, sec_name, "helptext");
2724 }
2725 }
2726
2728 if (ok) {
2730 }
2731
2732 return ok;
2733}
2734
2735/**********************************************************************/
2739static bool load_terrain_names(struct section_file *file,
2740 struct rscompat_info *compat)
2741{
2742 int nval = 0;
2743 struct section_list *sec = NULL;
2744 const char *flag;
2745 int i;
2746 const char *filename = secfile_name(file);
2747 bool ok = TRUE;
2748
2749 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2750 return FALSE;
2751 }
2752
2753 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2754 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2755
2756 /* User terrain flag names */
2757 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
2758 i++) {
2759 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
2760 i);
2761
2765 "\"%s\": Duplicate terrain flag name '%s'",
2766 filename, flag);
2767 ok = FALSE;
2768 break;
2769 }
2770 if (i > MAX_NUM_USER_TER_FLAGS) {
2772 "\"%s\": Too many user terrain flags!",
2773 filename);
2774 ok = FALSE;
2775 break;
2776 }
2777
2778 set_user_terrain_flag_name(TER_USER_1 + i, flag, helptxt);
2779 }
2780
2781 if (ok) {
2782 /* Blank the remaining terrain user flag slots. */
2783 for (; i < MAX_NUM_USER_TER_FLAGS; i++) {
2785 }
2786 }
2787
2788 /* User extra flag names */
2789 for (i = 0;
2790 (flag = secfile_lookup_str_default(file, NULL,
2791 "control.extra_flags%d.name",
2792 i));
2793 i++) {
2794 const char *helptxt = secfile_lookup_str_default(file, NULL,
2795 "control.extra_flags%d.helptxt", i);
2796
2798 != extra_flag_id_invalid()) {
2800 "\"%s\": Duplicate extra flag name '%s'",
2801 filename, flag);
2802 ok = FALSE;
2803 break;
2804 }
2807 "\"%s\": Too many user extra flags!",
2808 filename);
2809 ok = FALSE;
2810 break;
2811 }
2812
2813 set_user_extra_flag_name(EF_USER_FLAG_1 + i, flag, helptxt);
2814 }
2815
2816 if (ok) {
2817 /* Blank the remaining extra user flag slots. */
2818 for (; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
2820 }
2821
2822 /* Terrain names */
2823
2825 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2827 "\"%s\": ruleset doesn't have any terrains.",
2828 filename);
2829 ok = FALSE;
2830 } else {
2831 if (nval > MAX_NUM_TERRAINS) {
2833 "\"%s\": Too many terrains (%d, max %d)",
2834 filename, nval, MAX_NUM_TERRAINS);
2835 ok = FALSE;
2836 }
2837 }
2838 }
2839
2840 if (ok) {
2842
2843 /* avoid re-reading files */
2844 if (terrain_sections) {
2846 }
2848
2849 terrain_type_iterate(pterrain) {
2850 const int terri = terrain_index(pterrain);
2851 const char *sec_name = section_name(section_list_get(sec, terri));
2852
2853 if (!ruleset_load_names(&pterrain->name, NULL, file, sec_name)) {
2854 ok = FALSE;
2855 break;
2856 }
2857
2860 }
2861
2863 sec = NULL;
2864
2865 /* extra names */
2866
2867 if (ok) {
2869 nval = (NULL != sec ? section_list_size(sec) : 0);
2870 if (nval > MAX_EXTRA_TYPES) {
2872 "\"%s\": Too many extra types (%d, max %d)",
2873 filename, nval, MAX_EXTRA_TYPES);
2874 ok = FALSE;
2875 }
2876 }
2877
2878 if (ok) {
2879 int idx;
2880
2882
2883 if (extra_sections) {
2885 }
2887
2888 if (ok) {
2889 for (idx = 0; idx < nval; idx++) {
2890 const char *sec_name = section_name(section_list_get(sec, idx));
2891 struct extra_type *pextra = extra_by_number(idx);
2892
2893 if (!ruleset_load_names(&pextra->name, NULL, file, sec_name)) {
2894 ok = FALSE;
2895 break;
2896 }
2898 }
2899 }
2900 }
2901
2903 sec = NULL;
2904
2905 /* Base names */
2906
2907 if (ok) {
2909 nval = (NULL != sec ? section_list_size(sec) : 0);
2910 if (nval > MAX_EXTRA_TYPES) {
2912 "\"%s\": Too many base types (%d, max %d)",
2913 filename, nval, MAX_EXTRA_TYPES);
2914 ok = FALSE;
2915 }
2916
2918 }
2919
2920 if (ok) {
2921 int idx;
2922
2923 if (base_sections) {
2925 }
2927
2928 /* Cannot use base_type_iterate() before bases are added to
2929 * EC_BASE caused_by list. Have to get them by extra_type_by_rule_name() */
2930 for (idx = 0; idx < nval; idx++) {
2931 const char *sec_name = section_name(section_list_get(sec, idx));
2932 const char *base_name = secfile_lookup_str(file, "%s.extra", sec_name);
2933
2934 if (base_name != NULL) {
2936
2937 if (pextra != NULL) {
2938 base_type_init(pextra, idx);
2940 } else {
2942 "No extra definition matching base definition \"%s\"",
2943 base_name);
2944 ok = FALSE;
2945 }
2946 } else {
2948 "Base section \"%s\" does not associate base with any extra",
2949 sec_name);
2950 ok = FALSE;
2951 }
2952 }
2953 }
2954
2956 sec = NULL;
2957
2958 /* Road names */
2959
2960 if (ok) {
2962 nval = (NULL != sec ? section_list_size(sec) : 0);
2963 if (nval > MAX_EXTRA_TYPES) {
2965 "\"%s\": Too many road types (%d, max %d)",
2966 filename, nval, MAX_EXTRA_TYPES);
2967 ok = FALSE;
2968 }
2969
2971 }
2972
2973 if (ok) {
2974 int idx;
2975
2976 if (road_sections) {
2978 }
2980
2981 /* Cannot use extra_type_by_cause_iterate(EC_ROAD) before roads are added to
2982 * EC_ROAD caused_by list. Have to get them by extra_type_by_rule_name() */
2983 for (idx = 0; idx < nval; idx++) {
2984 const char *sec_name = section_name(section_list_get(sec, idx));
2985 const char *road_name = secfile_lookup_str(file, "%s.extra", sec_name);
2986
2987 if (road_name != NULL) {
2989
2990 if (pextra != NULL) {
2991 road_type_init(pextra, idx);
2993 } else {
2995 "No extra definition matching road definition \"%s\"",
2996 road_name);
2997 ok = FALSE;
2998 }
2999 } else {
3001 "Road section \"%s\" does not associate road with any extra",
3002 sec_name);
3003 ok = FALSE;
3004 }
3005 }
3006 }
3007
3009 sec = NULL;
3010
3011 /* Resource names */
3012 if (ok) {
3014 nval = (NULL != sec ? section_list_size(sec) : 0);
3015 if (nval > MAX_EXTRA_TYPES) {
3017 "\"%s\": Too many resource types (%d, max %d)",
3018 filename, nval, MAX_EXTRA_TYPES);
3019 ok = FALSE;
3020 }
3021
3023 }
3024
3025 if (ok) {
3026 int idx;
3027
3028 if (resource_sections) {
3030 }
3032
3033 /* Cannot use resource_type_iterate() before resource are added to
3034 * EC_RESOURCE caused_by list. Have to get them by extra_type_by_rule_name() */
3035 for (idx = 0; idx < nval; idx++) {
3036 const char *sec_name = section_name(section_list_get(sec, idx));
3037 const char *resource_name;
3038 struct extra_type *pextra = NULL;
3039
3041
3042 if (resource_name != NULL) {
3044
3045 if (pextra != NULL) {
3046 resource_type_init(pextra);
3048 } else {
3050 "No extra definition matching resource definition \"%s\"",
3052 ok = FALSE;
3053 }
3054 } else {
3056 "Resource section %s does not list extra this resource belongs to.",
3057 sec_name);
3058 ok = FALSE;
3059 }
3060 }
3061 }
3062
3064
3065 return ok;
3066}
3067
3068/**********************************************************************/
3071static bool load_ruleset_terrain(struct section_file *file,
3072 struct rscompat_info *compat)
3073{
3074 size_t nval, nval2;
3075 int j;
3076 bool compat_road = FALSE;
3077 bool compat_rail = FALSE;
3078 bool compat_river = FALSE;
3079 const char **res;
3080 const char *filename = secfile_name(file);
3081 const char *text;
3082 int *res_freq;
3083 bool ok = TRUE;
3084
3085 /* parameters */
3086
3087 terrain_control.ocean_reclaim_requirement_pct
3088 = secfile_lookup_int_default(file, 101,
3089 "parameters.ocean_reclaim_requirement");
3090 terrain_control.land_channel_requirement_pct
3091 = secfile_lookup_int_default(file, 101,
3092 "parameters.land_channel_requirement");
3093 terrain_control.terrain_thaw_requirement_pct
3094 = secfile_lookup_int_default(file, 101,
3095 "parameters.thaw_requirement");
3096 terrain_control.terrain_freeze_requirement_pct
3097 = secfile_lookup_int_default(file, 101,
3098 "parameters.freeze_requirement");
3099 terrain_control.lake_max_size
3101 "parameters.lake_max_size");
3102 terrain_control.min_start_native_area
3104 "parameters.min_start_native_area");
3105 terrain_control.move_fragments
3107 "parameters.move_fragments");
3108 if (terrain_control.move_fragments < 1) {
3110 "\"%s\": move_fragments must be at least 1",
3111 filename);
3112 ok = FALSE;
3113 }
3115 terrain_control.igter_cost
3117 "parameters.igter_cost");
3118 if (terrain_control.igter_cost < 1) {
3120 "\"%s\": igter_cost must be at least 1",
3121 filename);
3122 ok = FALSE;
3123 }
3124 terrain_control.infrapoints = FALSE; /* This will be updated if we find
3125 * an placeable extra. */
3126
3127 terrain_control.pythagorean_diagonal
3129 "parameters.pythagorean_diagonal");
3130
3133 "parameters.ocean_resources");
3134
3135 text = secfile_lookup_str_default(file,
3136 N_("?gui_type:Build Type A Base"),
3137 "extraui.ui_name_base_fortress");
3138 sz_strlcpy(terrain_control.gui_type_base0, text);
3139
3140 text = secfile_lookup_str_default(file,
3141 N_("?gui_type:Build Type B Base"),
3142 "extraui.ui_name_base_airbase");
3143 sz_strlcpy(terrain_control.gui_type_base1, text);
3144
3145 if (ok) {
3146 /* Terrain details */
3147
3148 terrain_type_iterate(pterrain) {
3149 const char **slist;
3150 const int i = terrain_index(pterrain);
3151 const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
3152 const char *cstr;
3153 const char *ename;
3154
3155 sz_strlcpy(pterrain->graphic_str,
3156 secfile_lookup_str(file, "%s.graphic", tsection));
3157 sz_strlcpy(pterrain->graphic_alt,
3159 "%s.graphic_alt", tsection));
3160 sz_strlcpy(pterrain->graphic_alt2,
3162 "%s.graphic_alt2", tsection));
3163
3164 pterrain->identifier
3165 = secfile_lookup_str(file, "%s.identifier", tsection)[0];
3166 if ('\0' == pterrain->identifier) {
3168 "\"%s\" [%s] identifier missing value.",
3169 filename, tsection);
3170 ok = FALSE;
3171 break;
3172 }
3173 if (TERRAIN_UNKNOWN_IDENTIFIER == pterrain->identifier) {
3175 "\"%s\" [%s] cannot use '%c' as an identifier;"
3176 " it is reserved for unknown terrain.",
3177 filename, tsection, pterrain->identifier);
3178 ok = FALSE;
3179 break;
3180 }
3181 for (j = T_FIRST; j < i; j++) {
3182 if (pterrain->identifier == terrain_by_number(j)->identifier) {
3184 "\"%s\" [%s] has the same identifier as [%s].",
3185 filename, tsection,
3187 ok = FALSE;
3188 break;
3189 }
3190 }
3191
3192 if (!ok) {
3193 break;
3194 }
3195
3196 cstr = secfile_lookup_str(file, "%s.class", tsection);
3197 pterrain->tclass = terrain_class_by_name(cstr, fc_strcasecmp);
3198 if (!terrain_class_is_valid(pterrain->tclass)) {
3200 "\"%s\": [%s] unknown class \"%s\"",
3201 filename, tsection, cstr);
3202 ok = FALSE;
3203 break;
3204 }
3205
3206 if (!secfile_lookup_int(file, &pterrain->movement_cost,
3207 "%s.movement_cost", tsection)
3208 || !secfile_lookup_int(file, &pterrain->defense_bonus,
3209 "%s.defense_bonus", tsection)) {
3211 ok = FALSE;
3212 break;
3213 }
3214
3216 pterrain->output[o]
3217 = secfile_lookup_int_default(file, 0, "%s.%s", tsection,
3220
3221 res = secfile_lookup_str_vec(file, &nval, "%s.resources", tsection);
3223 "%s.resource_freq", tsection);
3224 if (nval2 > 0 && nval2 != nval) {
3226 "\"%s\": [%s] Different lengths for resources "
3227 "and resource frequencies",
3228 filename, tsection);
3229 ok = FALSE;
3230 }
3231 pterrain->resources = fc_calloc(nval + 1, sizeof(*pterrain->resources));
3232 pterrain->resource_freq = fc_calloc(nval + 1,
3233 sizeof(*pterrain->resource_freq));
3234 for (j = 0; j < nval; j++) {
3235 pterrain->resources[j] = lookup_resource(filename, res[j], tsection);
3236 if (pterrain->resources[j] == NULL) {
3237 ok = FALSE;
3238 break;
3239 }
3240 pterrain->resource_freq[j] = j < nval2
3241 ? res_freq[j]
3243 if (pterrain->resource_freq[j] < RESOURCE_FREQUENCY_MINIMUM
3244 || pterrain->resource_freq[j] > RESOURCE_FREQUENCY_MAXIMUM) {
3246 "\"%s\": [%s] Resource frequency '%d' "
3247 "outside allowed range",
3248 filename, tsection,
3249 pterrain->resource_freq[j]);
3250 ok = FALSE;
3251 break;
3252 }
3253 }
3254 pterrain->resources[nval] = NULL;
3255 /* Terminating zero technically not necessary */
3256 pterrain->resource_freq[nval] = 0;
3257 free(res);
3258 res = NULL;
3259 free(res_freq);
3260 res_freq = NULL;
3261
3262 if (!ok) {
3263 break;
3264 }
3265
3267 pterrain->road_output_incr_pct[o]
3268 = secfile_lookup_int_default(file, 0, "%s.road_%s_incr_pct",
3271
3272 if (!lookup_time(file, &pterrain->base_time, tsection, "base_time",
3273 filename, NULL, &ok)
3274 || !lookup_time(file, &pterrain->road_time, tsection, "road_time",
3275 filename, NULL, &ok)) {
3277 ok = FALSE;
3278 break;
3279 }
3280
3281 if (!lookup_terrain(file, "cultivate_result", filename, pterrain,
3282 &pterrain->cultivate_result, FALSE)) {
3283 ruleset_error(NULL, LOG_ERROR, "%s: No cultivate_result", tsection);
3284 ok = FALSE;
3285 break;
3286 }
3287 if (pterrain->cultivate_result == pterrain) {
3289 "%s: Cultivating result in terrain itself.",
3290 tsection);
3291 ok = FALSE;
3292 break;
3293 }
3294 if (!secfile_lookup_int(file, &pterrain->irrigation_food_incr,
3295 "%s.irrigation_food_incr", tsection)
3296 || !lookup_time(file, &pterrain->irrigation_time,
3297 tsection, "irrigation_time", filename, NULL, &ok)) {
3299 ok = FALSE;
3300 break;
3301 }
3302
3303 if (!lookup_terrain(file, "plant_result", filename, pterrain,
3304 &pterrain->plant_result, FALSE)) {
3305 ruleset_error(NULL, LOG_ERROR, "%s: No plant_result", tsection);
3306 ok = FALSE;
3307 break;
3308 }
3309 if (pterrain->plant_result == pterrain) {
3311 "%s: Planting result in terrain itself.",
3312 tsection);
3313 ok = FALSE;
3314 break;
3315 }
3316 if (!secfile_lookup_int(file, &pterrain->mining_shield_incr,
3317 "%s.mining_shield_incr", tsection)
3318 || !lookup_time(file, &pterrain->mining_time,
3319 tsection, "mining_time", filename, NULL, &ok)) {
3321 ok = FALSE;
3322 break;
3323 }
3324
3325 if (!lookup_time(file, &pterrain->cultivate_time,
3326 tsection, "cultivate_time", filename, NULL, &ok)) {
3328 "%s: Missing cultivate_time", tsection);
3329 ok = FALSE;
3330 break;
3331 }
3332 if ((pterrain->cultivate_result != NULL
3333 && pterrain->cultivate_time <= 0)
3334 || (pterrain->cultivate_result == NULL
3335 && pterrain->cultivate_time > 0)) {
3337 "%s: cultivate_result and cultivate_time disagree "
3338 "whether cultivating is enabled", tsection);
3339 ok = FALSE;
3340 break;
3341 }
3342
3343 if (!lookup_time(file, &pterrain->plant_time,
3344 tsection, "plant_time", filename, NULL, &ok)) {
3346 "%s: Missing plant_time", tsection);
3347 ok = FALSE;
3348 break;
3349 }
3350 if ((pterrain->plant_result != NULL
3351 && pterrain->plant_time <= 0)
3352 || (pterrain->plant_result == NULL
3353 && pterrain->plant_time > 0)) {
3355 "%s: plant_result and plant_time disagree "
3356 "whether planting is enabled", tsection);
3357 ok = FALSE;
3358 break;
3359 }
3360
3361 if (!lookup_unit_type(file, tsection, "animal",
3362 &pterrain->animal, filename,
3363 rule_name_get(&pterrain->name))) {
3364 ok = FALSE;
3365 break;
3366 }
3367
3368 if (!lookup_terrain(file, "transform_result", filename, pterrain,
3369 &pterrain->transform_result, TRUE)) {
3370 ok = FALSE;
3371 break;
3372 }
3373 if (!lookup_time(file, &pterrain->transform_time,
3374 tsection, "transform_time", filename, NULL, &ok)) {
3376 ok = FALSE;
3377 break;
3378 }
3379 if ((pterrain->transform_result != NULL
3380 && pterrain->transform_time <= 0)
3381 || (pterrain->transform_result == NULL
3382 && pterrain->transform_time > 0)) {
3384 "%s: transform_result and transform_time disagree "
3385 "whether transforming is enabled", tsection);
3386 ok = FALSE;
3387 break;
3388 }
3389
3390 pterrain->placing_time = 1; /* Default */
3391 lookup_time(file, &pterrain->placing_time,
3392 tsection, "placing_time", filename, NULL, &ok);
3393
3394 pterrain->pillage_time = 1; /* Default */
3395 lookup_time(file, &pterrain->pillage_time,
3396 tsection, "pillage_time", filename, NULL, &ok);
3397
3398 if (!lookup_terrain(file, "warmer_wetter_result", filename, pterrain,
3399 &pterrain->warmer_wetter_result, TRUE)
3400 || !lookup_terrain(file, "warmer_drier_result", filename, pterrain,
3401 &pterrain->warmer_drier_result, TRUE)
3402 || !lookup_terrain(file, "cooler_wetter_result", filename, pterrain,
3403 &pterrain->cooler_wetter_result, TRUE)
3404 || !lookup_terrain(file, "cooler_drier_result", filename, pterrain,
3405 &pterrain->cooler_drier_result, TRUE)) {
3406 ok = FALSE;
3407 break;
3408 }
3409
3410 /* Set default removal times */
3411 extra_type_iterate(pextra) {
3412 pterrain->extra_removal_times[extra_index(pextra)] = 0;
3414
3415 for (j = 0; (ename = secfile_lookup_str_default(file, NULL,
3416 "%s.extra_settings%d.extra",
3417 tsection, j)); j++) {
3418 const struct extra_type *pextra = extra_type_by_rule_name(ename);
3419
3420 if (pextra != NULL) {
3421 char time_sections[512];
3422
3424 "%s.extra_settings%d", tsection, j);
3425
3426 lookup_time(file, &pterrain->extra_removal_times[extra_index(pextra)],
3427 time_sections, "removal_time", filename, NULL, &ok);
3428 } else {
3430 "\"%s\" [%s] has settings for unknown extra \"%s\".",
3431 filename, tsection, ename);
3432 ok = FALSE;
3433 break;
3434 }
3435 }
3436
3437 if (ok) {
3438 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsection);
3439 BV_CLR_ALL(pterrain->flags);
3440 for (j = 0; j < nval; j++) {
3441 const char *sval = slist[j];
3442 enum terrain_flag_id flag
3444
3445 if (!terrain_flag_id_is_valid(flag)) {
3447 "\"%s\" [%s] has unknown flag \"%s\".",
3448 filename, tsection, sval);
3449 ok = FALSE;
3450 break;
3451 } else {
3452 BV_SET(pterrain->flags, flag);
3453 }
3454 }
3455
3456 free(slist);
3457 }
3458
3459 if (!ok) {
3460 break;
3461 }
3462
3463 {
3465
3469 pterrain->property[mtp]
3470 = secfile_lookup_int_default(file, 0, "%s.property_%s", tsection,
3472 }
3473 }
3474
3475 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
3476 BV_CLR_ALL(pterrain->native_to);
3477 for (j = 0; j < nval; j++) {
3478 struct unit_class *class = unit_class_by_rule_name(slist[j]);
3479
3480 if (!class) {
3482 "\"%s\" [%s] is native to unknown unit class \"%s\".",
3483 filename, tsection, slist[j]);
3484 ok = FALSE;
3485 break;
3486 } else {
3487 BV_SET(pterrain->native_to, uclass_index(class));
3488 }
3489 }
3490 free(slist);
3491
3492 if (!ok) {
3493 break;
3494 }
3495
3496 /* Get terrain color */
3497 {
3498 fc_assert_ret_val(pterrain->rgb == NULL, FALSE);
3499
3500 if (!rgbcolor_load(file, &pterrain->rgb, "%s.color", tsection)) {
3502 "Missing terrain color definition: %s",
3503 secfile_error());
3504 ok = FALSE;
3505 break;
3506 }
3507 }
3508
3509 pterrain->helptext = lookup_strvec(file, tsection, "helptext");
3511 }
3512
3513 if (ok) {
3514 /* Extra details */
3515 extra_type_iterate(pextra) {
3516 BV_CLR_ALL(pextra->conflicts);
3518
3519 extra_type_iterate(pextra) {
3520 int eidx = extra_index(pextra);
3521 const char *section = &extra_sections[eidx * MAX_SECTION_LABEL];
3522 const char **slist;
3523 struct requirement_vector *reqs;
3524 const char *catname;
3525 int cj;
3526 enum extra_cause cause;
3528 const char *eus_name;
3529 const char *vis_req_name;
3530 const struct advance *vis_req;
3531
3532 catname = secfile_lookup_str(file, "%s.category", section);
3533 if (catname == NULL) {
3535 "\"%s\" extra \"%s\" has no category.",
3536 filename, extra_rule_name(pextra));
3537 ok = FALSE;
3538 break;
3539 }
3540 pextra->category = extra_category_by_name(catname, fc_strcasecmp);
3541 if (!extra_category_is_valid(pextra->category)) {
3543 "\"%s\" extra \"%s\" has invalid category \"%s\".",
3544 filename, extra_rule_name(pextra), catname);
3545 ok = FALSE;
3546 break;
3547 }
3548
3549 slist = secfile_lookup_str_vec(file, &nval, "%s.causes", section);
3550 pextra->causes = 0;
3551 for (cj = 0; cj < nval; cj++) {
3552 const char *sval = slist[cj];
3554
3555 if (!extra_cause_is_valid(cause)) {
3557 "\"%s\" extra \"%s\": unknown cause \"%s\".",
3558 filename, extra_rule_name(pextra), sval);
3559 ok = FALSE;
3560 break;
3561 } else {
3562 pextra->causes |= (1 << cause);
3563 extra_to_caused_by_list(pextra, cause);
3564 }
3565 }
3566
3567 if (pextra->causes == 0) {
3568 /* Extras that do not have any causes added to EC_NONE list */
3570 }
3571
3572 if (!is_extra_caused_by(pextra, EC_BASE)
3573 && !is_extra_caused_by(pextra, EC_ROAD)
3574 && !is_extra_caused_by(pextra, EC_RESOURCE)) {
3575 /* Not a base, road, nor resource, so special */
3576 pextra->data.special_idx = extra_type_list_size(extra_type_list_by_cause(EC_SPECIAL));
3578 }
3579
3580 free(slist);
3581
3582 slist = secfile_lookup_str_vec(file, &nval, "%s.rmcauses", section);
3583 pextra->rmcauses = 0;
3584 for (j = 0; j < nval; j++) {
3585 const char *sval = slist[j];
3586
3588
3591 "\"%s\" extra \"%s\": unknown rmcause \"%s\".",
3592 filename, extra_rule_name(pextra), sval);
3593 ok = FALSE;
3594 break;
3595 } else {
3596 pextra->rmcauses |= (1 << rmcause);
3598 }
3599 }
3600
3601 free(slist);
3602
3603 sz_strlcpy(pextra->activity_gfx,
3605 "%s.activity_gfx", section));
3606 sz_strlcpy(pextra->act_gfx_alt,
3608 "%s.act_gfx_alt", section));
3609 sz_strlcpy(pextra->act_gfx_alt2,
3611 "%s.act_gfx_alt2", section));
3612 sz_strlcpy(pextra->rmact_gfx,
3614 "%s.rmact_gfx", section));
3615 sz_strlcpy(pextra->rmact_gfx_alt,
3617 "%s.rmact_gfx_alt", section));
3618 sz_strlcpy(pextra->rmact_gfx_alt2,
3620 "%s.rmact_gfx_alt2", section));
3621 sz_strlcpy(pextra->graphic_str,
3622 secfile_lookup_str_default(file, "-", "%s.graphic", section));
3623 sz_strlcpy(pextra->graphic_alt,
3625 "%s.graphic_alt", section));
3626
3627 reqs = lookup_req_list(file, compat, section, "reqs", extra_rule_name(pextra));
3628 if (reqs == NULL) {
3629 ok = FALSE;
3630 break;
3631 }
3632 requirement_vector_copy(&pextra->reqs, reqs);
3633
3634 reqs = lookup_req_list(file, compat, section, "rmreqs", extra_rule_name(pextra));
3635 if (reqs == NULL) {
3636 ok = FALSE;
3637 break;
3638 }
3639 requirement_vector_copy(&pextra->rmreqs, reqs);
3640
3641 reqs = lookup_req_list(file, compat, section, "appearance_reqs", extra_rule_name(pextra));
3642 if (reqs == NULL) {
3643 ok = FALSE;
3644 break;
3645 }
3646 requirement_vector_copy(&pextra->appearance_reqs, reqs);
3647
3648 reqs = lookup_req_list(file, compat, section, "disappearance_reqs", extra_rule_name(pextra));
3649 if (reqs == NULL) {
3650 ok = FALSE;
3651 break;
3652 }
3653 requirement_vector_copy(&pextra->disappearance_reqs, reqs);
3654
3655 pextra->buildable = secfile_lookup_bool_default(file,
3657 "%s.buildable", section);
3658 pextra->generated = secfile_lookup_bool_default(file, TRUE,
3659 "%s.generated", section);
3660
3661 pextra->build_time = 0; /* default */
3662 lookup_time(file, &pextra->build_time, section, "build_time",
3663 filename, extra_rule_name(pextra), &ok);
3664 pextra->build_time_factor = secfile_lookup_int_default(file, 1,
3665 "%s.build_time_factor", section);
3666 pextra->removal_time = 0; /* default */
3667 lookup_time(file, &pextra->removal_time, section, "removal_time",
3668 filename, extra_rule_name(pextra), &ok);
3669 pextra->removal_time_factor = secfile_lookup_int_default(file, 1,
3670 "%s.removal_time_factor", section);
3671 pextra->infracost = secfile_lookup_int_default(file, 0,
3672 "%s.infracost", section);
3673 if (pextra->infracost > 0) {
3674 terrain_control.infrapoints = TRUE;
3675 }
3676
3677 pextra->defense_bonus = secfile_lookup_int_default(file, 0,
3678 "%s.defense_bonus",
3679 section);
3680 if (pextra->defense_bonus != 0) {
3681 if (extra_has_flag(pextra, EF_NATURAL_DEFENSE)) {
3683 } else {
3685 }
3686 }
3687
3688 eus_name = secfile_lookup_str_default(file, "Normal", "%s.unit_seen", section);
3690 if (!extra_unit_seen_type_is_valid(pextra->eus)) {
3692 "\"%s\" extra \"%s\" has illegal unit_seen value \"%s\".",
3693 filename, extra_rule_name(pextra), eus_name);
3694 ok = FALSE;
3695 break;
3696 }
3697 if (pextra->eus == EUS_HIDDEN) {
3699 }
3700
3701 pextra->appearance_chance = secfile_lookup_int_default(file, RS_DEFAULT_EXTRA_APPEARANCE,
3702 "%s.appearance_chance",
3703 section);
3704 pextra->disappearance_chance = secfile_lookup_int_default(file,
3706 "%s.disappearance_chance",
3707 section);
3708
3709 pextra->no_aggr_near_city = secfile_lookup_int_default(file, -1,
3710 "%s.no_aggr_near_city",
3711 section);
3712
3713 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
3714 BV_CLR_ALL(pextra->native_to);
3715 for (j = 0; j < nval; j++) {
3716 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
3717
3718 if (uclass == NULL) {
3720 "\"%s\" extra \"%s\" is native to unknown unit class \"%s\".",
3721 filename, extra_rule_name(pextra), slist[j]);
3722 ok = FALSE;
3723 break;
3724 } else {
3725 BV_SET(pextra->native_to, uclass_index(uclass));
3726 }
3727 }
3728 free(slist);
3729
3730 if (!ok) {
3731 break;
3732 }
3733
3734 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
3735 BV_CLR_ALL(pextra->flags);
3736 for (j = 0; j < nval; j++) {
3737 const char *sval = slist[j];
3738 enum extra_flag_id flag;
3739
3741
3742 if (!extra_flag_id_is_valid(flag)) {
3744 "\"%s\" extra \"%s\": unknown flag \"%s\".",
3745 filename, extra_rule_name(pextra), sval);
3746 ok = FALSE;
3747 break;
3748 } else {
3749 BV_SET(pextra->flags, flag);
3750 }
3751 }
3752 free(slist);
3753
3754 if (pextra->no_aggr_near_city >= 0) {
3756 }
3757
3758 if (extra_has_flag(pextra, EF_CAUSE_ZOC)) {
3760 }
3761
3762 if (!ok) {
3763 break;
3764 }
3765
3766 slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
3767 for (j = 0; j < nval; j++) {
3768 const char *sval = slist[j];
3770
3771 if (pextra2 == NULL) {
3773 "\"%s\" extra \"%s\": unknown conflict extra \"%s\".",
3774 filename, extra_rule_name(pextra), sval);
3775 ok = FALSE;
3776 break;
3777 } else {
3778 BV_SET(pextra->conflicts, extra_index(pextra2));
3779 BV_SET(pextra2->conflicts, extra_index(pextra));
3780 }
3781 }
3782
3783 free(slist);
3784
3785 if (!ok) {
3786 break;
3787 }
3788
3789 slist = secfile_lookup_str_vec(file, &nval, "%s.hidden_by", section);
3790 BV_CLR_ALL(pextra->hidden_by);
3791 for (j = 0; j < nval; j++) {
3792 const char *sval = slist[j];
3793 const struct extra_type *top = extra_type_by_rule_name(sval);
3794
3795 if (top == NULL) {
3797 "\"%s\" extra \"%s\" hidden by unknown extra \"%s\".",
3798 filename, extra_rule_name(pextra), sval);
3799 ok = FALSE;
3800 break;
3801 } else {
3802 BV_SET(pextra->hidden_by, extra_index(top));
3803 }
3804 }
3805 free(slist);
3806
3807 if (!ok) {
3808 break;
3809 }
3810
3811 slist = secfile_lookup_str_vec(file, &nval, "%s.bridged_over", section);
3812 BV_CLR_ALL(pextra->bridged_over);
3813 for (j = 0; j < nval; j++) {
3814 const char *sval = slist[j];
3815 const struct extra_type *top = extra_type_by_rule_name(sval);
3816
3817 if (top == NULL) {
3819 "\"%s\" extra \"%s\" bridged over unknown extra \"%s\".",
3820 filename, extra_rule_name(pextra), sval);
3821 ok = FALSE;
3822 break;
3823 } else {
3824 BV_SET(pextra->bridged_over, extra_index(top));
3825 }
3826 }
3827 free(slist);
3828
3829 if (!ok) {
3830 break;
3831 }
3832
3834 "%s.visibility_req", section);
3836
3837 if (vis_req == NULL) {
3839 "\"%s\" %s: unknown visibility_req %s.",
3840 filename, section, vis_req_name);
3841 ok = FALSE;
3842 break;
3843 }
3844
3845 pextra->visibility_req = advance_number(vis_req);
3846
3847 pextra->helptext = lookup_strvec(file, section, "helptext");
3849 }
3850
3851 if (ok) {
3852 int i = 0;
3853 /* Resource details */
3854
3856 char identifier[MAX_LEN_NAME];
3857 const char *id;
3859
3860 if (!presource->data.resource) {
3862 "\"%s\" extra \"%s\" has \"Resource\" cause but no "
3863 "corresponding [resource_*] section",
3864 filename, extra_rule_name(presource));
3865 ok = FALSE;
3866 break;
3867 }
3868
3870 presource->data.resource->output[o] =
3871 secfile_lookup_int_default(file, 0, "%s.%s", rsection,
3874
3875 id = secfile_lookup_str_default(file, NULL, "%s.identifier", rsection);
3876
3877 if (id == NULL) {
3878 presource->data.resource->id_old_save = '\0';
3879 } else {
3880 sz_strlcpy(identifier, id);
3881
3882 presource->data.resource->id_old_save = identifier[0];
3883 if (RESOURCE_NULL_IDENTIFIER == presource->data.resource->id_old_save) {
3885 "\"%s\" [%s] identifier missing value.",
3886 filename, rsection);
3887 ok = FALSE;
3888 break;
3889 }
3890 if (RESOURCE_NONE_IDENTIFIER == presource->data.resource->id_old_save) {
3892 "\"%s\" [%s] cannot use '%c' as an identifier;"
3893 " it is reserved.",
3894 filename, rsection, presource->data.resource->id_old_save);
3895 ok = FALSE;
3896 break;
3897 }
3898 }
3899
3900 if (!ok) {
3901 break;
3902 }
3903
3904 i++;
3906
3907 for (j = 0; ok && j < game.control.num_resource_types; j++) {
3908 const char *section = &resource_sections[j * MAX_SECTION_LABEL];
3909 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
3911
3912 if (!is_extra_caused_by(pextra, EC_RESOURCE)) {
3914 "\"%s\" resource section [%s]: extra \"%s\" does not "
3915 "have \"Resource\" in its causes",
3916 filename, section, extra_name);
3917 ok = FALSE;
3918 }
3919 }
3920 }
3921
3922 if (ok) {
3923 /* This can't be part of previous loop as we don't want random data from previous
3924 * ruleset to play havoc on us when we have only some resource identifiers loaded
3925 * from the new ruleset. */
3927 if (pres->data.resource->id_old_save != '\0') {
3929 if (pres->data.resource->id_old_save == pres2->data.resource->id_old_save
3930 && pres != pres2) {
3932 "\"%s\" [%s] has the same identifier as [%s].",
3933 filename,
3936 ok = FALSE;
3937 break;
3938 }
3940
3941 if (!ok) {
3942 break;
3943 }
3944 }
3946 }
3947
3948 if (ok) {
3949 /* Base details */
3951 struct base_type *pbase = extra_base_get(pextra);
3952 const char *section;
3953 const char *gui_str;
3954
3955 if (!pbase) {
3957 "\"%s\" extra \"%s\" has \"Base\" cause but no "
3958 "corresponding [base_*] section",
3959 filename, extra_rule_name(pextra));
3960 ok = FALSE;
3961 break;
3962 }
3964
3965 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
3967 if (!base_gui_type_is_valid(pbase->gui_type)) {
3969 "\"%s\" base \"%s\": unknown gui_type \"%s\".",
3970 filename, extra_rule_name(pextra), gui_str);
3971 ok = FALSE;
3972 break;
3973 }
3974
3975 pbase->border_sq = secfile_lookup_int_default(file, -1, "%s.border_sq",
3976 section);
3977 pbase->vision_main_sq = secfile_lookup_int_default(file, -1,
3978 "%s.vision_main_sq",
3979 section);
3980 pbase->vision_invis_sq = secfile_lookup_int_default(file, -1,
3981 "%s.vision_invis_sq",
3982 section);
3983 pbase->vision_subs_sq = secfile_lookup_int_default(file, -1,
3984 "%s.vision_subs_sq",
3985 section);
3986
3987 if (!ok) {
3988 break;
3989 }
3990
3993
3995 struct base_type *pbase2;
3996
3997 if (pextra == pextra2) {
3998 /* End of the fully initialized bases iteration. */
3999 break;
4000 }
4001
4004 BV_SET(pextra->conflicts, extra_index(pextra2));
4005 BV_SET(pextra2->conflicts, extra_index(pextra));
4006 }
4008 }
4010
4011 for (j = 0; ok && j < game.control.num_base_types; j++) {
4012 const char *section = &base_sections[j * MAX_SECTION_LABEL];
4013 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4015
4016 if (!is_extra_caused_by(pextra, EC_BASE)) {
4018 "\"%s\" base section [%s]: extra \"%s\" does not have "
4019 "\"Base\" in its causes",
4020 filename, section, extra_name);
4021 ok = FALSE;
4022 }
4023 }
4024 }
4025
4026 if (ok) {
4028 struct road_type *proad = extra_road_get(pextra);
4029 const char *section;
4030 const char **slist;
4031 const char *special;
4032 const char *modestr;
4033 struct requirement_vector *reqs;
4034 const char *gui_str;
4035
4036 if (!proad) {
4038 "\"%s\" extra \"%s\" has \"Road\" cause but no "
4039 "corresponding [road_*] section",
4040 filename, extra_rule_name(pextra));
4041 ok = FALSE;
4042 break;
4043 }
4045
4046 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4048 if (!road_gui_type_is_valid(proad->gui_type)) {
4050 "\"%s\" road \"%s\": unknown gui_type \"%s\".",
4051 filename, extra_rule_name(pextra), gui_str);
4052 ok = FALSE;
4053 break;
4054 }
4055
4056 reqs = lookup_req_list(file, compat, section, "first_reqs", extra_rule_name(pextra));
4057 if (reqs == NULL) {
4058 ok = FALSE;
4059 break;
4060 }
4061 requirement_vector_copy(&proad->first_reqs, reqs);
4062
4063 if (!secfile_lookup_int(file, &proad->move_cost,
4064 "%s.move_cost", section)) {
4065 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4066 ok = FALSE;
4067 break;
4068 }
4069
4070 modestr = secfile_lookup_str_default(file, "FastAlways", "%s.move_mode",
4071 section);
4073 if (!road_move_mode_is_valid(proad->move_mode)) {
4075 "Illegal move_mode \"%s\" for road \"%s\"",
4076 modestr, extra_rule_name(pextra));
4077 ok = FALSE;
4078 break;
4079 }
4080
4082 proad->tile_incr_const[o] =
4083 secfile_lookup_int_default(file, 0, "%s.%s_incr_const",
4085 proad->tile_incr[o] =
4086 secfile_lookup_int_default(file, 0, "%s.%s_incr",
4088 proad->tile_bonus[o] =
4089 secfile_lookup_int_default(file, 0, "%s.%s_bonus",
4092
4093 special = secfile_lookup_str_default(file, "None", "%s.compat_special", section);
4094 if (!fc_strcasecmp(special, "Road")) {
4095 if (compat_road) {
4097 "Multiple roads marked as compatibility \"Road\"");
4098 ok = FALSE;
4099 }
4100 compat_road = TRUE;
4101 proad->compat = ROCO_ROAD;
4102 } else if (!fc_strcasecmp(special, "Railroad")) {
4103 if (compat_rail) {
4105 "Multiple roads marked as compatibility \"Railroad\"");
4106 ok = FALSE;
4107 }
4108 compat_rail = TRUE;
4109 proad->compat = ROCO_RAILROAD;
4110 } else if (!fc_strcasecmp(special, "River")) {
4111 if (compat_river) {
4113 "Multiple roads marked as compatibility \"River\"");
4114 ok = FALSE;
4115 }
4117 proad->compat = ROCO_RIVER;
4118 } else if (!fc_strcasecmp(special, "None")) {
4119 proad->compat = ROCO_NONE;
4120 } else {
4122 "Illegal compatibility special \"%s\" for road %s",
4123 special, extra_rule_name(pextra));
4124 ok = FALSE;
4125 }
4126
4127 if (!ok) {
4128 break;
4129 }
4130
4131 slist = secfile_lookup_str_vec(file, &nval, "%s.integrates", section);
4132 BV_CLR_ALL(proad->integrates);
4133 for (j = 0; j < nval; j++) {
4134 const char *sval = slist[j];
4136 struct road_type *top = NULL;
4137
4138 if (textra != NULL) {
4139 top = extra_road_get(textra);
4140 }
4141
4142 if (top == NULL) {
4144 "\"%s\" road \"%s\" integrates with unknown road \"%s\".",
4145 filename, extra_rule_name(pextra), sval);
4146 ok = FALSE;
4147 break;
4148 } else {
4149 BV_SET(proad->integrates, road_number(top));
4150 }
4151 }
4152 free(slist);
4153
4154 if (!ok) {
4155 break;
4156 }
4157
4158 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
4159 BV_CLR_ALL(proad->flags);
4160 for (j = 0; j < nval; j++) {
4161 const char *sval = slist[j];
4163
4164 if (!road_flag_id_is_valid(flag)) {
4166 "\"%s\" road \"%s\": unknown flag \"%s\".",
4167 filename, extra_rule_name(pextra), sval);
4168 ok = FALSE;
4169 break;
4170 } else {
4171 BV_SET(proad->flags, flag);
4172 }
4173 }
4174 free(slist);
4175
4176 if (!ok) {
4177 break;
4178 }
4180
4181 for (j = 0; ok && j < game.control.num_road_types; j++) {
4182 const char *section = &road_sections[j * MAX_SECTION_LABEL];
4183 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4185
4186 if (!is_extra_caused_by(pextra, EC_ROAD)) {
4188 "\"%s\" road section [%s]: extra \"%s\" does not have "
4189 "\"Road\" in its causes",
4190 filename, section, extra_name);
4191 ok = FALSE;
4192 }
4193 }
4194 }
4195
4196 if (ok) {
4197 extra_type_iterate(pextra) {
4198 pextra->bridged = extra_type_list_new();
4200 if (BV_ISSET(pextra->bridged_over, pbridged->id)) {
4201 extra_type_list_append(pextra->bridged, pbridged);
4202 }
4205 }
4206
4207 if (ok) {
4209 }
4210
4211 return ok;
4212}
4213
4214/**********************************************************************/
4218static bool load_government_names(struct section_file *file,
4219 struct rscompat_info *compat)
4220{
4221 int nval = 0;
4222 struct section_list *sec;
4223 const char *filename = secfile_name(file);
4224 bool ok = TRUE;
4225
4226 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4227 return FALSE;
4228 }
4229
4230 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4231 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4232
4234 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
4235 ruleset_error(NULL, LOG_ERROR, "\"%s\": No governments?!?", filename);
4236 ok = FALSE;
4237 } else if (nval > G_LAST) {
4239 "\"%s\": Too many governments (%d, max %d)",
4240 filename, nval, G_LAST);
4241 ok = FALSE;
4242 }
4243
4244 if (ok) {
4246
4247 /* Government names are needed early so that get_government_by_name will
4248 * work. */
4249 governments_iterate(gov) {
4250 const char *sec_name =
4252
4253 if (!ruleset_load_names(&gov->name, NULL, file, sec_name)) {
4254 ok = FALSE;
4255 break;
4256 }
4258 }
4259
4261
4262 if (ok) {
4264 nval = (NULL != sec ? section_list_size(sec) : 0);
4265
4266 if (nval > MAX_NUM_MULTIPLIERS) {
4268 "\"%s\": Too many multipliers (%d, max %d)",
4269 filename, nval, MAX_NUM_MULTIPLIERS);
4270
4271 ok = FALSE;
4272 } else {
4274 }
4275
4276 if (ok) {
4277 multipliers_iterate(pmul) {
4278 const char *sec_name =
4280
4281 if (!ruleset_load_names(&pmul->name, NULL, file, sec_name)) {
4283 "\"%s\": Cannot load multiplier names",
4284 filename);
4285 ok = FALSE;
4286 break;
4287 }
4289 }
4290 }
4291
4293
4294 return ok;
4295}
4296
4297/**********************************************************************/
4301 struct rscompat_info *compat)
4302{
4303 struct section_list *sec;
4304 const char *filename = secfile_name(file);
4305 bool ok = TRUE;
4306
4308
4310 = lookup_government(file, "governments.during_revolution", filename, NULL);
4312 ok = FALSE;
4313 }
4314
4315 if (ok) {
4318
4319 /* Easy ones: */
4321 const int i = government_index(g);
4322 const char *sec_name = section_name(section_list_get(sec, i));
4323 struct requirement_vector *reqs
4325
4326 if (reqs == NULL) {
4327 ok = FALSE;
4328 break;
4329 }
4330
4331 if (NULL != secfile_entry_lookup(file, "%s.ai_better", sec_name)) {
4332 char entry[100];
4333
4334 fc_snprintf(entry, sizeof(entry), "%s.ai_better", sec_name);
4335 g->ai.better = lookup_government(file, entry, filename, NULL);
4336 if (g->ai.better == NULL) {
4337 ok = FALSE;
4338 break;
4339 }
4340 } else {
4341 g->ai.better = NULL;
4342 }
4343 requirement_vector_copy(&g->reqs, reqs);
4344
4345 sz_strlcpy(g->graphic_str,
4346 secfile_lookup_str(file, "%s.graphic", sec_name));
4347 sz_strlcpy(g->graphic_alt,
4348 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
4349 sz_strlcpy(g->sound_str,
4350 secfile_lookup_str_default(file, "-", "%s.sound", sec_name));
4351 sz_strlcpy(g->sound_alt,
4352 secfile_lookup_str_default(file, "-", "%s.sound_alt", sec_name));
4353 sz_strlcpy(g->sound_alt2,
4354 secfile_lookup_str_default(file, "-", "%s.sound_alt2", sec_name));
4355
4356 g->helptext = lookup_strvec(file, sec_name, "helptext");
4358 }
4359
4360
4361 if (ok) {
4362 /* Titles */
4364 const char *sec_name
4366 const char *male, *female;
4367
4368 if (!(male = secfile_lookup_str(file, "%s.ruler_male_title", sec_name))
4369 || !(female = secfile_lookup_str(file, "%s.ruler_female_title",
4370 sec_name))) {
4372 "Lack of default ruler titles for "
4373 "government \"%s\" (nb %d): %s",
4375 secfile_error());
4376 ok = FALSE;
4377 break;
4378 } else if (NULL == government_ruler_title_new(g, NULL, male, female)) {
4380 "Lack of default ruler titles for "
4381 "government \"%s\" (nb %d).",
4383 ok = FALSE;
4384 break;
4385 }
4387 }
4388
4390
4391 if (ok) {
4393 multipliers_iterate(pmul) {
4394 int id = multiplier_index(pmul);
4395 const char *sec_name = section_name(section_list_get(sec, id));
4396 struct requirement_vector *reqs;
4397
4398 if (!secfile_lookup_int(file, &pmul->start, "%s.start", sec_name)) {
4399 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4400 ok = FALSE;
4401 break;
4402 }
4403 if (!secfile_lookup_int(file, &pmul->stop, "%s.stop", sec_name)) {
4404 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4405 ok = FALSE;
4406 break;
4407 }
4408 if (pmul->stop <= pmul->start) {
4410 "Multiplier \"%s\" stop (%d) must be greater "
4411 "than start (%d)", multiplier_rule_name(pmul),
4412 pmul->stop, pmul->start);
4413 ok = FALSE;
4414 break;
4415 }
4416 if (!secfile_lookup_int(file, &pmul->step, "%s.step", sec_name)) {
4417 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4418 ok = FALSE;
4419 break;
4420 }
4421 if (((pmul->stop - pmul->start) % pmul->step) != 0) {
4423 "Multiplier \"%s\" step (%d) does not fit "
4424 "exactly into interval start-stop (%d to %d)",
4425 multiplier_rule_name(pmul), pmul->step,
4426 pmul->start, pmul->stop);
4427 ok = FALSE;
4428 break;
4429 }
4430 if (!secfile_lookup_int(file, &pmul->def, "%s.default", sec_name)) {
4431 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4432 ok = FALSE;
4433 break;
4434 }
4435 if (pmul->def < pmul->start || pmul->def > pmul->stop) {
4437 "Multiplier \"%s\" default (%d) not within "
4438 "legal range (%d to %d)", multiplier_rule_name(pmul),
4439 pmul->def, pmul->start, pmul->stop);
4440 ok = FALSE;
4441 break;
4442 }
4443 if (((pmul->def - pmul->start) % pmul->step) != 0) {
4445 "Multiplier \"%s\" default (%d) not legal "
4446 "with respect to step size %d",
4447 multiplier_rule_name(pmul), pmul->def, pmul->step);
4448 ok = FALSE;
4449 break;
4450 }
4451 pmul->offset = secfile_lookup_int_default(file, 0,
4452 "%s.offset", sec_name);
4453 pmul->factor = secfile_lookup_int_default(file, 100,
4454 "%s.factor", sec_name);
4455 if (pmul->factor == 0) {
4457 "Multiplier \"%s\" scaling factor must "
4458 "not be zero", multiplier_rule_name(pmul));
4459 ok = FALSE;
4460 break;
4461 }
4462
4463 pmul->minimum_turns = secfile_lookup_int_default(file, 0,
4464 "%s.minimum_turns",
4465 sec_name);
4466
4467 reqs = lookup_req_list(file, compat, sec_name, "reqs",
4468 multiplier_rule_name(pmul));
4469 if (reqs == NULL) {
4470 ok = FALSE;
4471 break;
4472 }
4473 requirement_vector_copy(&pmul->reqs, reqs);
4474
4475 pmul->helptext = lookup_strvec(file, sec_name, "helptext");
4478 }
4479
4480 if (ok) {
4482 }
4483
4484 return ok;
4485}
4486
4487/**********************************************************************/
4498static void send_ruleset_control(struct conn_list *dest)
4499{
4501 int idx = 0;
4502
4504
4505 if (game.ruleset_summary != NULL) {
4506 struct packet_ruleset_summary summary;
4507
4509
4510 lsend_packet_ruleset_summary(dest, &summary);
4511 }
4512
4513 while (desc_left > 0) {
4515 int this_len = desc_left;
4516
4517 if (this_len > MAX_LEN_CONTENT - 21) {
4519 }
4520
4521 part.text[this_len] = '\0';
4522
4524 idx += this_len;
4526
4528 }
4529}
4530
4531/**********************************************************************/
4536static const char *check_leader_names(struct nation_type *pnation)
4537{
4539 const char *name = nation_leader_name(pleader);
4540
4542 if (prev_leader == pleader) {
4543 break;
4544 } else if (0 == fc_strcasecmp(name, nation_leader_name(prev_leader))) {
4545 return name;
4546 }
4549 return NULL;
4550}
4551
4552/**********************************************************************/
4556static bool load_nation_names(struct section_file *file,
4557 struct rscompat_info *compat)
4558{
4559 struct section_list *sec;
4560 int j;
4561 bool ok = TRUE;
4562 const char *filename = secfile_name(file);
4563
4564 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4565 return FALSE;
4566 }
4567
4568 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4569 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4570
4572 if (NULL == sec) {
4574 "No available nations in this ruleset!");
4575 ok = FALSE;
4576 } else if (section_list_size(sec) > MAX_NUM_NATIONS) {
4578 "Too many nations (max %d, we have %d)!",
4580 ok = FALSE;
4581 } else {
4584
4586 const int i = nation_index(pl);
4587 const char *sec_name = section_name(section_list_get(sec, i));
4588 const char *domain = secfile_lookup_str_default(file, NULL,
4589 "%s.translation_domain", sec_name);
4590 const char *noun_plural = secfile_lookup_str(file,
4591 "%s.plural", sec_name);
4592
4593
4594 if (domain == NULL) {
4595 domain = "freeciv-nations";
4596 }
4597
4598 if (!strcmp("freeciv-core", domain)) {
4599 pl->translation_domain = NULL;
4600 } else if (!strcmp("freeciv-nations", domain)) {
4601 pl->translation_domain = fc_strdup(domain);
4602 } else {
4604 "Unsupported translation domain \"%s\" for %s",
4605 domain, sec_name);
4606 ok = FALSE;
4607 break;
4608 }
4609
4610 if (!ruleset_load_names(&pl->adjective, pl->translation_domain, file, sec_name)) {
4611 ok = FALSE;
4612 break;
4613 }
4614 name_set(&pl->noun_plural, pl->translation_domain, noun_plural);
4615
4616 /* Check if nation name is already defined. */
4617 for (j = 0; j < i && ok; j++) {
4618 struct nation_type *n2 = nation_by_number(j);
4619
4620 /* Compare strings after stripping off qualifiers -- we don't want
4621 * two nations to end up with identical adjectives displayed to users.
4622 * (This check only catches English, not localisations, of course.) */
4623 if (0 == strcmp(Qn_(untranslated_name(&n2->adjective)),
4624 Qn_(untranslated_name(&pl->adjective)))) {
4626 "Two nations defined with the same adjective \"%s\": "
4627 "in section \'%s\' and section \'%s\'",
4628 Qn_(untranslated_name(&pl->adjective)),
4630 ok = FALSE;
4631 } else if (!strcmp(rule_name_get(&n2->adjective),
4632 rule_name_get(&pl->adjective))) {
4633 /* We cannot have the same rule name, as the game needs them to be
4634 * distinct. */
4636 "Two nations defined with the same rule_name \"%s\": "
4637 "in section \'%s\' and section \'%s\'",
4638 rule_name_get(&pl->adjective),
4640 ok = FALSE;
4641 } else if (0 == strcmp(Qn_(untranslated_name(&n2->noun_plural)),
4642 Qn_(untranslated_name(&pl->noun_plural)))) {
4643 /* We don't want identical English plural names either. */
4645 "Two nations defined with the same plural name \"%s\": "
4646 "in section \'%s\' and section \'%s\'",
4647 Qn_(untranslated_name(&pl->noun_plural)),
4649 ok = FALSE;
4650 }
4651 }
4652 if (!ok) {
4653 break;
4654 }
4656 }
4657
4659
4660 if (ok) {
4662 if (sec != NULL) {
4664
4665 section_list_iterate(sec, psection) {
4666 struct nation_group *pgroup;
4667 const char *name;
4668
4669 name = secfile_lookup_str(file, "%s.name", section_name(psection));
4670 if (NULL == name) {
4671 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4672 ok = FALSE;
4673 break;
4674 }
4676 if (pgroup == NULL) {
4677 ok = FALSE;
4678 break;
4679 }
4682 sec = NULL;
4683 }
4684 }
4685
4686 return ok;
4687}
4688
4689/**********************************************************************/
4692static bool is_on_allowed_list(const char *name, const char **list, size_t len)
4693{
4694 int i;
4695
4696 for (i = 0; i < len; i++) {
4697 if (!fc_strcasecmp(name, list[i])) {
4698 return TRUE;
4699 }
4700 }
4701 return FALSE;
4702}
4703
4704/**********************************************************************/
4708static bool load_city_name_list(struct section_file *file,
4709 struct nation_type *pnation,
4710 const char *secfile_str1,
4711 const char *secfile_str2,
4712 const char **allowed_terrains,
4713 size_t atcount)
4714{
4715 size_t dim, j;
4716 bool ok = TRUE;
4717 const char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
4719
4720 /* Each string will be of the form "<cityname> (<label>, <label>, ...)".
4721 * The cityname is just the name for this city, while each "label" matches
4722 * a terrain type for the city (or "river"), with a preceding ! to negate
4723 * it. The parentheses are optional (but necessary to have the settings,
4724 * of course). Our job is now to parse it. */
4725 for (j = 0; j < dim; j++) {
4726 size_t len = strlen(cities[j]);
4727 char city_name[len + 1], *p, *next, *end;
4728 struct nation_city *pncity;
4729
4731
4732 /* Now we wish to determine values for all of the city labels. A value
4733 * of NCP_NONE means no preference (which is necessary so that the use
4734 * of this is optional); NCP_DISLIKE means the label is negated and
4735 * NCP_LIKE means it's labelled. Mostly the parsing just involves
4736 * a lot of ugly string handling... */
4737 if ((p = strchr(city_name, '('))) {
4738 *p++ = '\0';
4739
4740 if (!(end = strchr(p, ')'))) {
4742 "\"%s\" [%s] %s: city name \"%s\" "
4743 "unmatched parenthesis.", secfile_name(file),
4745 ok = FALSE;
4746 } else {
4747 for (*end++ = '\0'; '\0' != *end; end++) {
4748 if (!fc_isspace(*end)) {
4750 "\"%s\" [%s] %s: city name \"%s\" "
4751 "contains characters after last parenthesis.",
4753 cities[j]);
4754 ok = FALSE;
4755 break;
4756 }
4757 }
4758 }
4759 }
4760
4761 /* Build the nation_city. */
4764 /* The ruleset contains a name that is too long. This shouldn't
4765 * happen - if it does, the author should get immediate feedback. */
4767 "\"%s\" [%s] %s: city name \"%s\" is too long.",
4768 secfile_name(file),
4770 ok = FALSE;
4771 city_name[MAX_LEN_CITYNAME - 1] = '\0';
4772 }
4773 pncity = nation_city_new(pnation, city_name);
4774
4775 if (NULL != p) {
4776 /* Handle the labels one at a time. */
4777 do {
4778 enum nation_city_preference prefer;
4779
4780 if ((next = strchr(p, ','))) {
4781 *next = '\0';
4782 }
4784
4785 /* The ! is used to mark a negative, which is recorded with
4786 * NCP_DISLIKE. Otherwise we use a NCP_LIKE.
4787 */
4788 if (*p == '!') {
4789 p++;
4790 prefer = NCP_DISLIKE;
4791 } else {
4792 prefer = NCP_LIKE;
4793 }
4794
4795 if (0 == fc_strcasecmp(p, "river")) {
4797 && !is_on_allowed_list(p,
4800 "\"%s\" [%s] %s: city \"%s\" "
4801 "has terrain hint \"%s\" not in allowed_terrains.",
4803 city_name, p);
4804 ok = FALSE;
4805 } else {
4807 }
4808 } else {
4809 const struct terrain *pterrain = terrain_by_rule_name(p);
4810
4811 if (NULL == pterrain) {
4812 /* Try with removing frequent trailing 's'. */
4813 size_t l = strlen(p);
4814
4815 if (0 < l && 's' == fc_tolower(p[l - 1])) {
4816 char saved = p[l - 1];
4817
4818 p[l - 1] = '\0';
4819 pterrain = terrain_by_rule_name(p);
4820 if (pterrain == NULL) {
4821 /* Didn't help, restore for later allowed_terrains check */
4822 p[l - 1] = saved;
4823 }
4824 }
4825 }
4826
4827 /* Nationset may have been devised with a specific set of terrains
4828 * in mind which don't quite match this ruleset, in which case we
4829 * (a) quietly ignore any hints mentioned that don't happen to be in
4830 * the current ruleset, (b) enforce that terrains mentioned by nations
4831 * must be on the list */
4832 if (pterrain != NULL && game.server.ruledit.allowed_terrains != NULL) {
4833 if (!is_on_allowed_list(p,
4835 /* Terrain exists, but not intended for these nations */
4837 "\"%s\" [%s] %s: city \"%s\" "
4838 "has terrain hint \"%s\" not in allowed_terrains.",
4840 city_name, p);
4841 ok = FALSE;
4842 break;
4843 }
4844 } else if (!pterrain) {
4845 /* Terrain doesn't exist; only complain if it's not on any list */
4847 || !is_on_allowed_list(p,
4850 "\"%s\" [%s] %s: city \"%s\" "
4851 "has unknown terrain hint \"%s\".",
4853 city_name, p);
4854 ok = FALSE;
4855 break;
4856 }
4857 }
4858 if (NULL != pterrain) {
4859 nation_city_set_terrain_preference(pncity, pterrain, prefer);
4860 }
4861 }
4862
4863 p = next ? next + 1 : NULL;
4864 } while (NULL != p && '\0' != *p);
4865 }
4866 }
4867
4868 if (NULL != cities) {
4869 free(cities);
4870 }
4871
4872 return ok;
4873}
4874
4875/**********************************************************************/
4878static bool load_ruleset_nations(struct section_file *file,
4879 struct rscompat_info *compat)
4880{
4881 struct government *gov;
4882 int j;
4883 size_t dim;
4884 char temp_name[MAX_LEN_NAME];
4885 const char **vec;
4886 const char *name, *bad_leader;
4887 const char *sval;
4888 int default_set;
4889 const char *filename = secfile_name(file);
4890 struct section_list *sec = NULL;
4891 enum trait tr;
4892 bool ok = TRUE;
4893
4894 name = secfile_lookup_str_default(file, NULL, "ruledit.nationlist");
4895 if (name != NULL) {
4897 }
4899 "ruledit.embedded_nations");
4900
4901 if (vec != NULL) {
4902 /* Copy to persistent vector */
4905
4906 for (j = 0; j < game.server.ruledit.embedded_nations_count; j++) {
4908 }
4909
4910 free(vec);
4911 }
4912
4914
4915 ruleset_load_traits(game.server.default_traits, file, "default_traits", "");
4916 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
4917 if (game.server.default_traits[tr].min < 0) {
4919 }
4920 if (game.server.default_traits[tr].max < 0) {
4922 }
4923 if (game.server.default_traits[tr].fixed < 0) {
4925
4926 /* TODO: Should sometimes round the a / 2 = x.5 results up */
4928 }
4931 "Default values for trait %s not sane.",
4932 trait_name(tr));
4933 ok = FALSE;
4934 break;
4935 }
4936 }
4937
4938 if (ok) {
4940 "compatibility.allowed_govs");
4941 if (vec != NULL) {
4942 /* Copy to persistent vector */
4944 = fc_malloc(game.server.ruledit.ag_count * sizeof(char *));
4946 (const char **)game.server.ruledit.nc_agovs;
4947
4948 for (j = 0; j < game.server.ruledit.ag_count; j++) {
4950 }
4951
4952 free(vec);
4953 }
4954
4956 "compatibility.allowed_terrains");
4957 if (vec != NULL) {
4958 /* Copy to persistent vector */
4960 = fc_malloc(game.server.ruledit.at_count * sizeof(char *));
4962 (const char **)game.server.ruledit.nc_aterrs;
4963
4964 for (j = 0; j < game.server.ruledit.at_count; j++) {
4966 }
4967
4968 free(vec);
4969 }
4970
4972 "compatibility.allowed_styles");
4973 if (vec != NULL) {
4974 /* Copy to persistent vector */
4976 = fc_malloc(game.server.ruledit.as_count * sizeof(char *));
4978 (const char **)game.server.ruledit.nc_astyles;
4979
4980 for (j = 0; j < game.server.ruledit.as_count; j++) {
4982 }
4983
4984 free(vec);
4985 }
4986
4988 "compatibility.default_government");
4989 /* We deliberately don't check this against allowed_govs. It's only
4990 * specified once so not vulnerable to typos, and may usefully be set in
4991 * a specific ruleset to a gov not explicitly known by the nation set. */
4992 if (sval != NULL) {
4994 if (game.default_government == NULL) {
4996 "Tried to set unknown government type \"%s\" as default_government!",
4997 sval);
4998 ok = FALSE;
4999 } else {
5002 }
5003 }
5004 }
5005
5006 if (ok) {
5008 if (sec != NULL) {
5010
5011 section_list_iterate(sec, psection) {
5012 const char *set_name, *set_rule_name, *set_description;
5013
5014 set_name = secfile_lookup_str(file, "%s.name", section_name(psection));
5016 secfile_lookup_str(file, "%s.rule_name", section_name(psection));
5017 set_description = secfile_lookup_str_default(file, "", "%s.description",
5018 section_name(psection));
5019 if (NULL == set_name || NULL == set_rule_name) {
5020 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5021 ok = FALSE;
5022 break;
5023 }
5025 ok = FALSE;
5026 break;
5027 }
5030 sec = NULL;
5031 } else {
5033 "At least one nation set [" NATION_SET_SECTION_PREFIX "_*] "
5034 "must be defined.");
5035 ok = FALSE;
5036 }
5037 }
5038
5039 if (ok) {
5040 /* Default set that every nation is a member of. */
5042 "compatibility.default_nationset");
5043 if (sval != NULL) {
5045 if (pset != NULL) {
5047 } else {
5049 "Unknown default_nationset \"%s\".", sval);
5050 ok = FALSE;
5051 }
5052 } else if (nation_set_count() == 1) {
5053 /* If there's only one set defined, every nation is implicitly a
5054 * member of that set. */
5055 default_set = 0;
5056 } else {
5057 /* No default nation set; every nation must explicitly specify at
5058 * least one set to be a member of. */
5059 default_set = -1;
5060 }
5061 }
5062
5063 if (ok) {
5065 if (sec) {
5066 section_list_iterate(sec, psection) {
5067 struct nation_group *pgroup;
5068 bool hidden;
5069
5070 name = secfile_lookup_str(file, "%s.name", section_name(psection));
5072 if (pgroup == NULL) {
5073 ok = FALSE;
5074 break;
5075 }
5076
5077 hidden = secfile_lookup_bool_default(file, FALSE, "%s.hidden",
5078 section_name(psection));
5080
5081 if (!secfile_lookup_int(file, &j, "%s.match", section_name(psection))) {
5082 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5083 ok = FALSE;
5084 break;
5085 }
5089 sec = NULL;
5090 }
5091 }
5092
5093 if (ok) {
5095 nations_iterate(pnation) {
5096 struct nation_type *pconflict;
5097 const int i = nation_index(pnation);
5098 char tmp[200] = "\0";
5099 const char *barb_type;
5100 const char *sec_name = section_name(section_list_get(sec, i));
5101 const char *legend;
5102
5103 /* Nation sets and groups. */
5104 if (default_set >= 0) {
5105 nation_set_list_append(pnation->sets,
5107 }
5108 vec = secfile_lookup_str_vec(file, &dim, "%s.groups", sec_name);
5109 for (j = 0; j < dim; j++) {
5110 struct nation_set *pset = nation_set_by_rule_name(vec[j]);
5112
5113 fc_assert(pset == NULL || pgroup == NULL);
5114
5115 if (NULL != pset) {
5116 nation_set_list_append(pnation->sets, pset);
5117 } else if (NULL != pgroup) {
5118 nation_group_list_append(pnation->groups, pgroup);
5119 } else {
5120 /* For nation authors, this would probably be considered an error.
5121 * But it can happen normally. The civ1 compatibility ruleset only
5122 * uses the nations that were in civ1, so not all of the links will
5123 * exist. */
5124 log_verbose("Nation %s: Unknown set/group \"%s\".",
5125 nation_rule_name(pnation), vec[j]);
5126 }
5127 }
5128 if (NULL != vec) {
5129 free(vec);
5130 }
5131 if (nation_set_list_size(pnation->sets) < 1) {
5133 "Nation %s is not a member of any nation set",
5134 nation_rule_name(pnation));
5135 ok = FALSE;
5136 break;
5137 }
5138
5139 /* Nation conflicts. */
5140 vec = secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec_name);
5141 for (j = 0; j < dim; j++) {
5143
5144 if (pnation == pconflict) {
5146 "Nation %s conflicts with itself",
5147 nation_rule_name(pnation));
5148 ok = FALSE;
5149 break;
5150 } else if (NULL != pconflict) {
5151 nation_list_append(pnation->server.conflicts_with, pconflict);
5152 } else {
5153 /* For nation authors, this would probably be considered an error.
5154 * But it can happen normally. The civ1 compatibility ruleset only
5155 * uses the nations that were in civ1, so not all of the links will
5156 * exist. */
5157 log_verbose("Nation %s: conflicts_with nation \"%s\" is unknown.",
5158 nation_rule_name(pnation), vec[j]);
5159 }
5160 }
5161 if (NULL != vec) {
5162 free(vec);
5163 }
5164 if (!ok) {
5165 break;
5166 }
5167
5168 /* Nation leaders. */
5169 for (j = 0; j < MAX_NUM_LEADERS; j++) {
5170 const char *sexstr;
5171 sex_t sex;
5172 bool is_male = FALSE;
5173
5174 name = secfile_lookup_str(file, "%s.leaders%d.name", sec_name, j);
5175 if (NULL == name) {
5176 /* No more to read. */
5177 break;
5178 }
5179
5180 if (check_name(name)) {
5181 /* The ruleset contains a name that is too long. This shouldn't
5182 * happen - if it does, the author should get immediate feedback */
5185 "Nation %s: leader name \"%s\" is too long.",
5186 nation_rule_name(pnation), name);
5187 ok = FALSE;
5188 break;
5189 }
5190
5191 sexstr = secfile_lookup_str(file, "%s.leaders%d.sex", sec_name, j);
5192 if (NULL == sexstr) {
5194 "Nation %s: leader \"%s\": %s.",
5195 nation_rule_name(pnation), name, secfile_error());
5196 ok = FALSE;
5197 break;
5198 }
5199
5201
5202 switch (sex) {
5203 case SEX_MALE:
5204 is_male = TRUE;
5205 break;
5206 case SEX_FEMALE:
5207 is_male = FALSE;
5208 break;
5209 case SEX_UNKNOWN:
5211 "Nation %s: leader \"%s\" has unsupported "
5212 "sex variant \"%s\".",
5213 nation_rule_name(pnation), name, sexstr);
5214 ok = FALSE;
5215 break;
5216 }
5217
5218 if (ok) {
5219 (void) nation_leader_new(pnation, name, is_male);
5220 }
5221 }
5222 if (!ok) {
5223 break;
5224 }
5225
5226 /* Check the number of leaders. */
5227 if (MAX_NUM_LEADERS == j) {
5228 /* Too much leaders, get the real number defined in the ruleset. */
5229 while (NULL != secfile_entry_lookup(file, "%s.leaders%d.name",
5230 sec_name, j)) {
5231 j++;
5232 }
5234 "Nation %s: Too many leaders; max is %d",
5236 ok = FALSE;
5237 break;
5238 } else if (0 == j) {
5240 "Nation %s: no leaders; at least one is required.",
5241 nation_rule_name(pnation));
5242 ok = FALSE;
5243 break;
5244 }
5245
5246 /* Check if leader name is not already defined in this nation. */
5247 if ((bad_leader = check_leader_names(pnation))) {
5249 "Nation %s: leader \"%s\" defined more than once.",
5250 nation_rule_name(pnation), bad_leader);
5251 ok = FALSE;
5252 break;
5253 }
5254
5255 /* Nation player color preference, if any */
5256 fc_assert_ret_val(pnation->server.rgb == NULL, FALSE);
5257 (void) rgbcolor_load(file, &pnation->server.rgb, "%s.color", sec_name);
5258
5259 /* Load nation traits */
5260 ruleset_load_traits(pnation->server.traits, file, sec_name, "trait_");
5261 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5262 bool server_traits_used = TRUE;
5263
5264 if (pnation->server.traits[tr].min < 0) {
5265 pnation->server.traits[tr].min = game.server.default_traits[tr].min;
5266 } else {
5268 }
5269 if (pnation->server.traits[tr].max < 0) {
5270 pnation->server.traits[tr].max = game.server.default_traits[tr].max;
5271 } else {
5273 }
5274 if (pnation->server.traits[tr].fixed < 0) {
5275 if (server_traits_used) {
5276 pnation->server.traits[tr].fixed = game.server.default_traits[tr].fixed;
5277 } else {
5278 int diff = pnation->server.traits[tr].max - pnation->server.traits[tr].min;
5279
5280 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5281 pnation->server.traits[tr].fixed = diff / 2 + pnation->server.traits[tr].min;
5282 }
5283 }
5284 if (pnation->server.traits[tr].max < pnation->server.traits[tr].min) {
5286 "%s values for trait %s not sane.",
5287 nation_rule_name(pnation), trait_name(tr));
5288 ok = FALSE;
5289 break;
5290 }
5291 }
5292
5293 if (!ok) {
5294 break;
5295 }
5296
5297 pnation->is_playable =
5298 secfile_lookup_bool_default(file, TRUE, "%s.is_playable", sec_name);
5299
5300 /* Check barbarian type. Default is "None" meaning not a barbarian */
5301 barb_type = secfile_lookup_str_default(file, "None",
5302 "%s.barbarian_type", sec_name);
5303 pnation->barb_type = barbarian_type_by_name(barb_type, fc_strcasecmp);
5304 if (!barbarian_type_is_valid(pnation->barb_type)) {
5306 "Nation %s, barbarian_type is invalid (\"%s\")",
5307 nation_rule_name(pnation), barb_type);
5308 ok = FALSE;
5309 break;
5310 }
5311
5312 if (pnation->barb_type != NOT_A_BARBARIAN
5313 && pnation->is_playable) {
5314 /* We can't allow players to use barbarian nations, barbarians
5315 * may run out of nations */
5317 "Nation %s marked both barbarian and playable.",
5318 nation_rule_name(pnation));
5319 ok = FALSE;
5320 break;
5321 }
5322
5323 /* Flags */
5324 sz_strlcpy(pnation->flag_graphic_str,
5325 secfile_lookup_str_default(file, "-", "%s.flag", sec_name));
5326 sz_strlcpy(pnation->flag_graphic_alt,
5328 "%s.flag_alt", sec_name));
5329
5330 /* Ruler titles */
5331 for (j = 0;; j++) {
5332 const char *male, *female;
5333
5335 "%s.ruler_titles%d.government",
5336 sec_name, j);
5337 if (NULL == name) {
5338 /* End of the list of ruler titles. */
5339 break;
5340 }
5341
5342 /* NB: even if the government doesn't exist, we load the entries for
5343 * the ruler titles to avoid warnings about unused entries. */
5344 male = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
5345 sec_name, j);
5346 female = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
5347 sec_name, j);
5349
5350 /* Nationset may have been devised with a specific set of govs in
5351 * mind which don't quite match this ruleset, in which case we
5352 * (a) quietly ignore any govs mentioned that don't happen to be in
5353 * the current ruleset, (b) enforce that govs mentioned by nations
5354 * must be on the list */
5355 if (gov != NULL && game.server.ruledit.allowed_govs != NULL) {
5359 /* Gov exists, but not intended for these nations */
5360 gov = NULL;
5362 "Nation %s: government \"%s\" not in allowed_govs.",
5363 nation_rule_name(pnation), name);
5364 ok = FALSE;
5365 break;
5366 }
5367 } else if (!gov) {
5368 /* Gov doesn't exist; only complain if it's not on any list */
5374 "Nation %s: government \"%s\" not found.",
5375 nation_rule_name(pnation), name);
5376 ok = FALSE;
5377 break;
5378 }
5379 }
5380 if (NULL != male && NULL != female) {
5381 if (gov) {
5382 (void) government_ruler_title_new(gov, pnation, male, female);
5383 }
5384 } else {
5386 ok = FALSE;
5387 break;
5388 }
5389 }
5390 if (!ok) {
5391 break;
5392 }
5393
5394 /* City styles */
5395 name = secfile_lookup_str(file, "%s.style", sec_name);
5396 if (!name) {
5398 ok = FALSE;
5399 break;
5400 }
5401 pnation->style = style_by_rule_name(name);
5402 if (pnation->style == NULL) {
5408 "Nation %s: Illegal style \"%s\"",
5409 nation_rule_name(pnation), name);
5410 ok = FALSE;
5411 break;
5412 } else {
5413 log_verbose("Nation %s: style \"%s\" not supported in this "
5414 "ruleset; using default.",
5415 nation_rule_name(pnation), name);
5416 pnation->style = style_by_number(0);
5417 }
5418 }
5419
5420 /* Civilwar nations */
5421 vec = secfile_lookup_str_vec(file, &dim,
5422 "%s.civilwar_nations", sec_name);
5423 for (j = 0; j < dim; j++) {
5425
5426 /* No test for duplicate nations is performed. If there is a duplicate
5427 * entry it will just cause that nation to have an increased
5428 * probability of being chosen. */
5429 if (pconflict == pnation) {
5431 "Nation %s is its own civil war nation",
5432 nation_rule_name(pnation));
5433 ok = FALSE;
5434 break;
5435 } else if (NULL != pconflict) {
5436 nation_list_append(pnation->server.civilwar_nations, pconflict);
5437 nation_list_append(pconflict->server.parent_nations, pnation);
5438 } else {
5439 /* For nation authors, this would probably be considered an error.
5440 * But it can happen normally. The civ1 compatibility ruleset only
5441 * uses the nations that were in civ1, so not all of the links will
5442 * exist. */
5443 log_verbose("Nation %s: civil war nation \"%s\" is unknown.",
5444 nation_rule_name(pnation), vec[j]);
5445 }
5446 }
5447 if (NULL != vec) {
5448 free(vec);
5449 }
5450 if (!ok) {
5451 break;
5452 }
5453
5454 /* Load nation specific initial items */
5455 if (!lookup_tech_list(file, sec_name, "init_techs",
5456 pnation->init_techs, filename)) {
5457 ok = FALSE;
5458 break;
5459 }
5460 if (!lookup_building_list(file, sec_name, "init_buildings",
5461 pnation->init_buildings, filename)) {
5462 ok = FALSE;
5463 break;
5464 }
5465 if (!lookup_unit_list(file, sec_name, "init_units",
5466 pnation->init_units, filename)) {
5467 ok = FALSE;
5468 break;
5469 }
5470 fc_strlcat(tmp, sec_name, 200);
5471 fc_strlcat(tmp, ".init_government", 200);
5472 if (secfile_entry_by_path(file, tmp)) {
5473 pnation->init_government = lookup_government(file, tmp, filename,
5474 NULL);
5475 /* If specified, init_government has to be in this specific ruleset,
5476 * not just allowed_govs */
5477 if (pnation->init_government == NULL) {
5478 ok = FALSE;
5479 break;
5480 }
5481 /* ...but if a list of govs has been specified, enforce that this
5482 * nation's init_government is on the list. */
5484 && !is_on_allowed_list(government_rule_name(pnation->init_government),
5488 "Nation %s: init_government \"%s\" not allowed.",
5489 nation_rule_name(pnation),
5490 government_rule_name(pnation->init_government));
5491 ok = FALSE;
5492 break;
5493 }
5494 }
5495
5496 /* Read default city names. */
5497 if (!load_city_name_list(file, pnation, sec_name, "cities",
5500 ok = FALSE;
5501 break;
5502 }
5503
5504 legend = secfile_lookup_str_default(file, "", "%s.legend", sec_name);
5505 pnation->legend = fc_strdup(legend);
5506 if (check_strlen(pnation->legend, MAX_LEN_MSG, NULL)) {
5508 "Nation %s: legend \"%s\" is too long.",
5509 nation_rule_name(pnation),
5510 pnation->legend);
5511 ok = FALSE;
5512 break;
5513 }
5514
5515 pnation->player = NULL;
5518 sec = NULL;
5519 }
5520
5521 /* Clean up on aborted load */
5522 if (sec != NULL) {
5523 fc_assert(!ok);
5525 }
5526
5527 if (ok) {
5529 }
5530
5531 if (ok) {
5532 /* Update cached number of playable nations in the current set */
5534
5535 /* Sanity checks on all sets */
5538
5539 nations_iterate(pnation) {
5540 if (nation_is_in_set(pnation, pset)) {
5541 switch (nation_barbarian_type(pnation)) {
5542 case NOT_A_BARBARIAN:
5543 if (is_nation_playable(pnation)) {
5544 num_playable++;
5545 }
5546 break;
5547 case LAND_BARBARIAN:
5549 break;
5550 case SEA_BARBARIAN:
5552 break;
5553 case ANIMAL_BARBARIAN:
5554 /* Animals are optional */
5555 break;
5558 break;
5559 default:
5561 }
5562 }
5564 if (num_playable < 1) {
5566 "Nation set \"%s\" has no playable nations. "
5567 "At least one required!", nation_set_rule_name(pset));
5568 ok = FALSE;
5569 break;
5570 }
5571 if (barb_land_count == 0 && barb_both_count == 0) {
5573 "No land barbarian nation defined in set \"%s\". "
5574 "At least one required!", nation_set_rule_name(pset));
5575 ok = FALSE;
5576 break;
5577 }
5578 if (barb_sea_count == 0 && barb_both_count == 0) {
5580 "No sea barbarian nation defined in set \"%s\". "
5581 "At least one required!", nation_set_rule_name(pset));
5582 ok = FALSE;
5583 break;
5584 }
5586 }
5587
5588 return ok;
5589}
5590
5591/**********************************************************************/
5595static bool load_style_names(struct section_file *file,
5596 struct rscompat_info *compat)
5597{
5598 bool ok = TRUE;
5599 struct section_list *sec;
5600 const char *filename = secfile_name(file);
5601
5602 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5603 return FALSE;
5604 }
5605
5606 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5607 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5608
5610 if (NULL == sec) {
5612 "No available nation styles in this ruleset!");
5613 ok = FALSE;
5614 } else {
5616
5618
5620 const int i = style_index(ps);
5621 const char *sec_name = section_name(section_list_get(sec, i));
5622
5623 ruleset_load_names(&ps->name, NULL, file, sec_name);
5625 }
5626
5628
5629 if (ok) {
5630 /* The citystyle sections: */
5631 int i = 0;
5632
5634 if (NULL != sec) {
5636 section_list_iterate(sec, style) {
5637 if (!ruleset_load_names(&city_styles[i].name, NULL, file, section_name(style))) {
5638 ok = FALSE;
5639 break;
5640 }
5641 i++;
5643
5645 } else {
5647 }
5648 }
5649
5650 return ok;
5651}
5652
5653/**********************************************************************/
5656static bool load_ruleset_styles(struct section_file *file,
5657 struct rscompat_info *compat)
5658{
5659 struct section_list *sec;
5660 int i;
5661 bool ok = TRUE;
5662
5663 /* City Styles ... */
5664
5666
5667 /* Get rest: */
5668 for (i = 0; i < game.control.num_city_styles; i++) {
5669 struct requirement_vector *reqs;
5670 const char *sec_name = section_name(section_list_get(sec, i));
5671
5672 sz_strlcpy(city_styles[i].graphic,
5673 secfile_lookup_str(file, "%s.graphic", sec_name));
5674 sz_strlcpy(city_styles[i].graphic_alt,
5675 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
5676 sz_strlcpy(city_styles[i].citizens_graphic,
5678 "%s.citizens_graphic", sec_name));
5679
5681 if (reqs == NULL) {
5682 ok = FALSE;
5683 break;
5684 }
5686 }
5687
5689
5690 if (ok) {
5692
5693 if (sec != NULL) {
5694 int musi;
5695
5698 musi = 0;
5699
5700 section_list_iterate(sec, psection) {
5701 struct requirement_vector *reqs;
5703 const char *sec_name = section_name(psection);
5704
5705 sz_strlcpy(pmus->music_peaceful,
5707 "%s.music_peaceful", sec_name));
5708 sz_strlcpy(pmus->music_combat,
5710 "%s.music_combat", sec_name));
5711
5712 reqs = lookup_req_list(file, compat, sec_name, "reqs", "Music Style");
5713 if (reqs == NULL) {
5714 ok = FALSE;
5715 break;
5716 }
5718
5719 musi++;
5721 }
5722
5724 }
5725
5726 return ok;
5727}
5728
5729/**********************************************************************/
5736 const char *uflags_path,
5737 const char *filename)
5738{
5739 /* Add each listed protected unit type flag as a !present
5740 * requirement. */
5741 if (secfile_entry_lookup(file, "%s", uflags_path)) {
5743 size_t psize;
5744 int i;
5745
5748 "%s", uflags_path);
5749
5750 if (!protecor_flag) {
5751 /* Entity exists but couldn't read it. */
5753 "\"%s\": %s: bad unit type flag list.",
5754 filename, uflags_path);
5755
5756 return FALSE;
5757 }
5758
5759 for (i = 0; i < psize; i++) {
5763 FALSE, FALSE, TRUE,
5764 protecor_flag[i]));
5765 }
5766
5768 }
5769
5770 return TRUE;
5771}
5772
5773/**********************************************************************/
5779 const char *actions_path,
5780 const char *filename)
5781{
5782 /* Read the alternative actions. */
5783 if (secfile_entry_lookup(file, "%s", actions_path)) {
5784 enum gen_action *unit_acts;
5785 size_t asize;
5786 int i;
5787
5789 "%s", actions_path);
5790
5791 if (!unit_acts) {
5792 /* Entity exists but couldn't read it. */
5794 "\"%s\": %s: bad action list",
5795 filename, actions_path);
5796
5797 return FALSE;
5798 }
5799
5800 for (i = 0; i < asize; i++) {
5801 auto_perf->alternatives[i] = unit_acts[i];
5802 }
5803
5804 free(unit_acts);
5805 }
5806
5807 return TRUE;
5808}
5809
5810/**********************************************************************/
5815 const char *item,
5816 const char *filename)
5817{
5818 char uflags_path[100];
5819 char action_path[100];
5820
5822 "missing_unit_upkeep.%s_protected", item);
5824 "missing_unit_upkeep.%s_unit_act", item);
5825
5827 filename)
5829 filename));
5830}
5831
5832/**********************************************************************/
5835static bool load_ruleset_cities(struct section_file *file,
5836 struct rscompat_info *compat)
5837{
5838 const char *filename = secfile_name(file);
5839 const char *item;
5840 struct section_list *sec;
5841 bool ok = TRUE;
5842
5843 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5844 return FALSE;
5845 }
5846
5847 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5848 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5849
5850 /* Specialist options */
5852 if (!sec) {
5853 ruleset_error(NULL, LOG_ERROR, "\"%s\": No specialists.", filename);
5854 ok = FALSE;
5855 } else if (section_list_size(sec) >= SP_MAX) {
5857 "\"%s\": Too many specialists (%d, max %d).",
5858 filename, section_list_size(sec), SP_MAX);
5859 ok = FALSE;
5860 }
5861
5862 if (ok) {
5863 int i = 0;
5864 const char *tag;
5865
5867
5868 section_list_iterate(sec, psection) {
5869 struct specialist *s = specialist_by_number(i);
5870 struct requirement_vector *reqs;
5871 const char *sec_name = section_name(psection);
5872
5873 if (!ruleset_load_names(&s->name, NULL, file, sec_name)) {
5874 ok = FALSE;
5875 break;
5876 }
5877
5879 "%s.short_name", sec_name);
5881
5882 tag = secfile_lookup_str(file, "%s.graphic", sec_name);
5883 if (tag == NULL) {
5885 "\"%s\": No graphic tag for specialist at %s.",
5886 filename, sec_name);
5887 ok = FALSE;
5888 break;
5889 }
5890 sz_strlcpy(s->graphic_str, tag);
5893 "%s.graphic_alt", sec_name));
5894
5896 if (reqs == NULL) {
5897 ok = FALSE;
5898 break;
5899 }
5901
5902 s->helptext = lookup_strvec(file, sec_name, "helptext");
5903
5904 if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
5906 }
5907 i++;
5909 }
5910
5911 if (ok && DEFAULT_SPECIALIST == -1) {
5913 "\"%s\": must have zero reqs for at least one "
5914 "specialist type.", filename);
5915 ok = FALSE;
5916 }
5918 sec = NULL;
5919
5920 if (ok) {
5921 /* City Parameters */
5922
5925 "parameters.celebrate_size_limit");
5927 secfile_lookup_int_default(file, GAME_DEFAULT_ADDTOSIZE, "parameters.add_to_size_limit");
5930 "parameters.angry_citizens");
5931
5933 secfile_lookup_bool_default(file, GAME_DEFAULT_CHANGABLE_TAX, "parameters.changable_tax");
5935 secfile_lookup_int_default(file, 0, "parameters.forced_science");
5937 secfile_lookup_int_default(file, 100, "parameters.forced_luxury");
5939 secfile_lookup_int_default(file, 0, "parameters.forced_gold");
5941 + game.info.forced_gold != 100) {
5943 "\"%s\": Forced taxes do not add up in ruleset!",
5944 filename);
5945 ok = FALSE;
5946 }
5947 }
5948
5949 if (ok) {
5950 /* civ1 & 2 didn't reveal tiles */
5953 "parameters.vision_reveal_tiles");
5954
5956 secfile_lookup_int_default(file, 1, "parameters.pop_report_zeroes");
5957
5958 /* Citizens configuration. */
5961 "citizen.nationality");
5964 "citizen.ubuilder_nationality");
5967 "citizen.convert_speed");
5969 secfile_lookup_int_default(file, 0, "citizen.partisans_pct");
5971 secfile_lookup_int_default(file, 0, "citizen.conquest_convert_pct");
5972 }
5973
5974 if (ok) {
5975 /* Missing unit upkeep. */
5977
5978 /* Can't pay food upkeep! */
5980 auto_perf->cause = AAPC_UNIT_UPKEEP;
5981
5982 /* This is about food upkeep. */
5984 req_from_str("OutputType", "Local",
5985 FALSE, TRUE, TRUE,
5986 "Food"));
5987
5988 /* Internally represented as an action auto performer rule. */
5989 if (!load_muuk_as_action_auto(file, auto_perf, "food", filename)) {
5990 ok = FALSE;
5991 }
5992
5995 "missing_unit_upkeep.food_wipe");
5996
5997 /* Can't pay gold upkeep! */
5999 auto_perf->cause = AAPC_UNIT_UPKEEP;
6000
6001 /* This is about gold upkeep. */
6003 req_from_str("OutputType", "Local",
6004 FALSE, TRUE, TRUE,
6005 "Gold"));
6006
6007 /* Internally represented as an action auto performer rule. */
6008 if (!load_muuk_as_action_auto(file, auto_perf, "gold", filename)) {
6009 ok = FALSE;
6010 }
6011
6014 "missing_unit_upkeep.gold_wipe");
6015
6016 /* Can't pay shield upkeep! */
6018 auto_perf->cause = AAPC_UNIT_UPKEEP;
6019
6020 /* This is about shield upkeep. */
6022 req_from_str("OutputType", "Local",
6023 FALSE, TRUE, TRUE,
6024 "Shield"));
6025
6026 /* Internally represented as an action auto performer rule. */
6027 if (!load_muuk_as_action_auto(file, auto_perf, "shield", filename)) {
6028 ok = FALSE;
6029 }
6030
6033 "missing_unit_upkeep.shield_wipe");
6034 }
6035
6036 if (ok) {
6038 }
6039
6040 return ok;
6041}
6042
6043/**********************************************************************/
6046static bool load_ruleset_effects(struct section_file *file,
6047 struct rscompat_info *compat)
6048{
6049 struct section_list *sec;
6050 const char *filename;
6051 bool ok = TRUE;
6052
6053 filename = secfile_name(file);
6054
6055 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6056 return FALSE;
6057 }
6058
6059 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6060 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6061
6063
6064 if (sec != NULL) {
6065 section_list_iterate(sec, psection) {
6066 const char *sec_name = section_name(psection);
6067 enum effect_type main_type;
6068 enum effect_type ai_valued_as;
6069 const char *type;
6070
6071 type = secfile_lookup_str(file, "%s.type", sec_name);
6072 if (type == NULL) {
6074 "\"%s\" [%s] missing effect type.",
6075 filename, sec_name);
6076 ok = FALSE;
6077 break;
6078 }
6082 "\"%s\" [%s] lists unknown effect type \"%s\".",
6083 filename, sec_name, type);
6084 ok = FALSE;
6085 break;
6086 }
6087 if (!is_user_effect(main_type)) {
6089 "\"%s\" [%s] type \"%s\" is not an user effect.",
6090 filename, sec_name, type);
6091 ok = FALSE;
6092 break;
6093 }
6094
6095 type = secfile_lookup_str(file, "%s.ai_valued_as", sec_name);
6096 if (type == NULL) {
6098 "\"%s\" [%s] missing ai_valued_as.",
6099 filename, sec_name);
6100 ok = FALSE;
6101 break;
6102 }
6106 "\"%s\" [%s] lists unknown ai_valued_as \"%s\".",
6107 filename, sec_name, type);
6108 ok = FALSE;
6109 break;
6110 }
6113 "\"%s\" [%s] ai_valued_as \"%s\" is an user effect.",
6114 filename, sec_name, type);
6115 ok = FALSE;
6116 break;
6117 }
6118
6120 /* It has been set already! */
6122 "\"%s\" [%s] Duplicate \"%s\" entry.",
6123 filename, sec_name, type);
6124 ok = FALSE;
6125 break;
6126 }
6127
6130
6132 }
6133
6134 /* Parse effects and add them to the effects ruleset cache. */
6136 section_list_iterate(sec, psection) {
6137 enum effect_type eff;
6138 int value;
6139 struct multiplier *pmul;
6140 struct effect *peffect;
6141 const char *sec_name = section_name(psection);
6142 struct requirement_vector *reqs;
6143 const char *type;
6144 const char *comment;
6145
6146 type = secfile_lookup_str(file, "%s.type", sec_name);
6147
6148 if (type == NULL) {
6150 "\"%s\" [%s] missing effect type.",
6151 filename, sec_name);
6152 ok = FALSE;
6153 break;
6154 }
6155
6156 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
6158 }
6159
6161 if (!effect_type_is_valid(eff)) {
6163 "\"%s\" [%s] lists unknown effect type \"%s\".",
6164 filename, sec_name, type);
6165 ok = FALSE;
6166 break;
6167 }
6168
6169 value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
6170
6171 {
6172 const char *multiplier_name
6173 = secfile_lookup_str(file, "%s.multiplier", sec_name);
6174
6175 if (multiplier_name) {
6177 if (!pmul) {
6179 "\"%s\" [%s] has unknown multiplier \"%s\".",
6180 filename, sec_name, multiplier_name);
6181 ok = FALSE;
6182 break;
6183 }
6184 } else {
6185 pmul = NULL;
6186 }
6187 }
6188
6189 peffect = effect_new(eff, value, pmul);
6190
6191 reqs = lookup_req_list(file, compat, sec_name, "reqs", type);
6192 if (reqs == NULL) {
6193 ok = FALSE;
6194 break;
6195 }
6196
6200
6201 comment = secfile_lookup_str_default(file, NULL, "%s.comment", sec_name);
6202
6203 if (comment != NULL) {
6204 peffect->rulesave.comment = fc_strdup(comment);
6205 }
6206
6209
6210 if (ok) {
6212 }
6213
6214 return ok;
6215}
6216
6217/**********************************************************************/
6220static int secfile_lookup_int_default_min_max(struct section_file *file,
6221 int def, int min, int max,
6222 const char *path, ...)
6225 int def, int min, int max,
6226 const char *path, ...)
6227{
6228 char fullpath[256];
6229 int ival;
6230 va_list args;
6231
6232 va_start(args, path);
6233 fc_vsnprintf(fullpath, sizeof(fullpath), path, args);
6234 va_end(args);
6235
6236 if (!secfile_lookup_int(file, &ival, "%s", fullpath)) {
6237 ival = def;
6238 }
6239
6240 if (ival < min) {
6242 "\"%s\" should be in the interval [%d, %d] "
6243 "but is %d; using the minimal value.",
6244 fullpath, min, max, ival);
6245 ival = min;
6246 }
6247
6248 if (ival > max) {
6250 "\"%s\" should be in the interval [%d, %d] "
6251 "but is %d; using the maximal value.",
6252 fullpath, min, max, ival);
6253 ival = max;
6254 }
6255
6256 return ival;
6257}
6258
6259/**********************************************************************/
6262static bool load_action_range_max(struct section_file *file, action_id act)
6263{
6264 struct action *paction = action_by_number(act);
6265 const char *vname = action_max_range_ruleset_var_name(act);
6266
6267 if (vname != NULL) {
6268 struct entry *pentry;
6269 int max_range;
6270
6271 pentry = secfile_entry_lookup(file, "actions.%s", vname);
6272
6273 if (pentry == NULL) {
6275 } else {
6276 const char *custom;
6277
6280 /* max_range already assigned */
6281 } else if (entry_type_get(pentry) == ENTRY_STR
6285 } else {
6286 ruleset_error(NULL, LOG_ERROR, "Bad actions.%s",
6289
6290 return FALSE;
6291 }
6292 }
6293
6295 }
6296
6297 return TRUE;
6298}
6299
6300/**********************************************************************/
6303static bool load_action_range(struct section_file *file, action_id act)
6304{
6305 struct action *paction = action_by_number(act);
6306 const char *vname;
6307
6308 if (!load_action_range_max(file, act)) {
6309 return FALSE;
6310 }
6311
6313 if (vname != NULL) {
6314 /* Min range can be loaded from the ruleset. */
6318 "actions.%s",
6319 vname);
6320 }
6321
6322 return TRUE;
6323}
6324
6325/**********************************************************************/
6328static bool load_action_kind(struct section_file *file, action_id act)
6329{
6330 struct action *paction = action_by_number(act);
6332
6333 if (var_name != NULL) {
6337 paction->result),
6339 "actions.%s", var_name);
6340 } else {
6343 }
6344
6345 return TRUE;
6346}
6347
6348/**********************************************************************/
6352 action_id act)
6353{
6355 /* Actor consumption can be loaded from the ruleset. */
6358 file, RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS, "actions.%s",
6360 }
6361
6362 return TRUE;
6363}
6364
6365/**********************************************************************/
6369 const char *filename,
6370 struct action *paction,
6371 struct rscompat_info *compat)
6372{
6374
6375 if (var_name != nullptr) {
6376 /* Action blocking can be loaded from the ruleset. */
6377 char fullpath[1024];
6378
6379 fc_snprintf(fullpath, sizeof(fullpath), "actions.%s", var_name);
6380
6381 if (secfile_entry_by_path(file, fullpath)) {
6383 size_t asize;
6384 int j;
6385
6388
6389 if (!blocking_actions) {
6390 /* Entity exists but couldn't read it. */
6392 "\"%s\": %s: bad action list",
6393 filename, fullpath);
6394
6395 return FALSE;
6396 }
6397
6398 for (j = 0; j < asize; j++) {
6399 BV_SET(paction->blocked_by, blocking_actions[j]);
6400 }
6401
6403 } else if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
6405
6406 if (secfile_entry_by_path(file, fullpath)) {
6408 size_t asize;
6409 int j;
6410
6413
6414 if (!blocking_actions) {
6415 /* Entity exists but couldn't read it. */
6417 "\"%s\": %s: bad action list",
6418 filename, fullpath);
6419
6420 return FALSE;
6421 }
6422
6423 for (j = 0; j < asize; j++) {
6424 BV_SET(paction->blocked_by, blocking_actions[j]);
6425 }
6426
6428 }
6429 }
6430 }
6431
6432 return TRUE;
6433}
6434
6435/**********************************************************************/
6440 const char *filename,
6441 int performer_slot,
6442 struct action *paction)
6443{
6445 char action_list_path[100];
6446
6448 /* Not relevant. */
6449 return TRUE;
6450 }
6451
6453 auto_perf->cause = AAPC_POST_ACTION;
6454
6455 /* Limit auto performer to this action. */
6458 FALSE, TRUE, TRUE,
6459 paction->id));
6460
6461 /* Load the list of actions. */
6463 "actions.%s",
6466 action_list_path, filename)) {
6467 return FALSE;
6468 }
6469
6470 return TRUE;
6471}
6472
6473/**********************************************************************/
6476static bool lookup_bv_actions(struct section_file *file,
6477 const char *filename,
6478 bv_actions *target,
6479 const char *path)
6480{
6481 if (secfile_entry_by_path(file, path)) {
6483 size_t asize;
6484 int j;
6485
6487 "%s", path);
6488
6489 if (!listed_actions) {
6490 /* Entity exists but couldn't read it. */
6491 ruleset_error(NULL, LOG_ERROR, "\"%s\": %s: bad action list",
6492 filename, path);
6493
6494 return FALSE;
6495 }
6496
6497 for (j = 0; j < asize; j++) {
6498 BV_SET(*target, listed_actions[j]);
6499 }
6500
6502 }
6503
6504 return TRUE;
6505}
6506
6507/**********************************************************************/
6510static bool load_ruleset_game(struct section_file *file, bool act,
6511 struct rscompat_info *compat)
6512{
6513 const char *sval, **svec;
6514 const char *filename;
6515 int *food_ini;
6516 int i;
6517 size_t teams;
6518 const char *pref_text;
6519 size_t gni_tmp;
6520 struct section_list *sec;
6521 size_t nval;
6522 const char *name;
6523 bool ok = TRUE;
6524
6525 if (file == NULL) {
6526 return FALSE;
6527 }
6528 filename = secfile_name(file);
6529
6530 name = secfile_lookup_str_default(file, NULL, "ruledit.description_file");
6531 if (name != NULL) {
6533 }
6535 = secfile_lookup_bool_default(file, FALSE, "ruledit.std_tileset_compat");
6536
6537 /* Section: tileset */
6538 pref_text = secfile_lookup_str_default(file, "", "tileset.preferred");
6539 if (pref_text[0] != '\0') {
6540 /* There was tileset suggestion */
6542 } else {
6543 /* No tileset suggestions */
6544 game.control.preferred_tileset[0] = '\0';
6545 }
6546
6547 /* Section: soundset */
6548 pref_text = secfile_lookup_str_default(file, "", "soundset.preferred");
6549 if (pref_text[0] != '\0') {
6550 /* There was soundset suggestion */
6552 } else {
6553 /* No soundset suggestions */
6555 }
6556
6557 /* Section: musicset */
6558 pref_text = secfile_lookup_str_default(file, "", "musicset.preferred");
6559 if (pref_text[0] != '\0') {
6560 /* There was musicset suggestion */
6562 } else {
6563 /* No musicset suggestions */
6565 }
6566
6567 /* Section: about */
6568 pref_text = secfile_lookup_str(file, "about.name");
6569 /* Ruleset/modpack name found */
6571
6572 pref_text = secfile_lookup_str_default(file, "", "about.version");
6573 if (pref_text[0] != '\0') {
6574 /* Ruleset/modpack version found */
6576 } else {
6577 /* No version information */
6578 game.control.version[0] = '\0';
6579 }
6580
6581 pref_text = secfile_lookup_str_default(file, "", "about.alt_dir");
6582 if (pref_text[0] != '\0') {
6583 /* Alt directory definition found. */
6585 } else {
6586 /* No alt directory information */
6587 game.control.alt_dir[0] = '\0';
6588 }
6589
6590 pref_text = secfile_lookup_str_default(file, "", "about.summary");
6591 if (pref_text[0] != '\0') {
6592 int len;
6593
6594 /* Ruleset/modpack summary found */
6595 len = strlen(pref_text);
6598 } else {
6599 /* No summary */
6600 if (game.ruleset_summary != NULL) {
6603 }
6604 }
6605
6606 pref_text = secfile_lookup_str_default(file, "", "about.description");
6607 if (pref_text[0] != '\0') {
6608 int len;
6609
6610 /* Ruleset/modpack description found */
6611 len = strlen(pref_text);
6615 } else {
6616 /* No description */
6617 if (game.ruleset_description != NULL) {
6620 }
6622 }
6623
6624 pref_text = secfile_lookup_str_default(file, "", "about.capabilities");
6625 if (pref_text[0] != '\0') {
6626 int len = strlen(pref_text);
6627
6630 } else {
6632 game.ruleset_capabilities[0] = '\0';
6633 }
6634
6635 /* Section: options */
6636 if (!lookup_tech_list(file, "options", "global_init_techs",
6637 game.rgame.global_init_techs, filename)) {
6638 ok = FALSE;
6639 }
6640
6641 if (ok) {
6642 if (!lookup_building_list(file, "options", "global_init_buildings",
6643 game.rgame.global_init_buildings, filename)) {
6644 ok = FALSE;
6645 }
6646 }
6647
6648 if (ok) {
6649 const char **slist;
6650 int j;
6651
6653 "options.popup_tech_help");
6654
6655 /* section: civstyle */
6658 "civstyle.base_pollution");
6659
6661
6662 slist = secfile_lookup_str_vec(file, &nval, "civstyle.gameloss_style");
6663 for (j = 0; j < nval; j++) {
6664 enum gameloss_style style;
6665
6666 sval = slist[j];
6667 if (strcmp(sval, "") == 0) {
6668 continue;
6669 }
6671 if (!gameloss_style_is_valid(style)) {
6673 "\"%s\": bad value \"%s\" for gameloss_style.",
6674 filename, sval);
6675 ok = FALSE;
6676 break;
6677 } else {
6678 game.info.gameloss_style |= style;
6679 }
6680 }
6681 free(slist);
6682 }
6683
6684 if (ok) {
6690 "civstyle.happy_cost");
6696 "civstyle.food_cost");
6697
6698 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
6700 = secfile_lookup_bool_default(file, TRUE, "civstyle.civil_war_enabled");
6702 } else {
6703 /* Avoid additional Civil War enabler */
6705 }
6706
6712 "civstyle.base_bribe_cost");
6718 "civstyle.ransom_gold");
6721 "civstyle.pillage_select");
6722
6725 "civstyle.tech_steal_allow_holes");
6728 "civstyle.tech_trade_allow_holes");
6731 "civstyle.tech_trade_loss_allow_holes");
6734 "civstyle.tech_parasite_allow_holes");
6737 "civstyle.tech_loss_allow_holes");
6738
6744 "civstyle.upgrade_veteran_loss");
6750 "civstyle.autoupgrade_veteran_loss");
6751
6757 "research.base_tech_cost");
6758
6764 "research.min_tech_cost");
6765
6767 "civstyle.granary_food_ini");
6769
6772 "Too many granary_food_ini entries (%d, max %d)",
6774 ok = FALSE;
6775 } else if (game.info.granary_num_inis == 0) {
6776 log_error("No values for granary_food_ini. Using default "
6777 "value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
6780 } else {
6781 int gi;
6782
6783 /* check for <= 0 entries */
6784 for (gi = 0; gi < game.info.granary_num_inis; gi++) {
6785 if (food_ini[gi] <= 0) {
6786 if (gi == 0) {
6788 } else {
6789 food_ini[gi] = food_ini[gi - 1];
6790 }
6791 log_error("Bad value for granary_food_ini[%i]. Using %i.",
6792 gi, food_ini[gi]);
6793 }
6795 }
6796 }
6797 free(food_ini);
6798 }
6799
6800 if (ok) {
6806 "civstyle.granary_food_inc");
6807
6814 "civstyle.min_city_center_%s",
6817 }
6818
6819 if (ok) {
6820 const char *tus_text;
6821
6827 "civstyle.init_vis_radius_sq");
6828
6834 "civstyle.init_city_radius_sq");
6835
6837 "civstyle.gold_upkeep_style");
6842 "Unknown gold upkeep style \"%s\"",
6843 tus_text);
6844 ok = FALSE;
6845 }
6846
6848 = secfile_lookup_bool_default(file, FALSE, "civstyle.homeless_gold_upkeep");
6849
6853 "Cannot have homeless_gold_upkeep while gold_upkeep_style \"City\".");
6854 ok = FALSE;
6855 }
6856
6858 "civstyle.output_granularity");
6859
6861 = secfile_lookup_bool_default(file, FALSE, "civstyle.airlift_from_always_enabled");
6862
6864 = secfile_lookup_bool_default(file, TRUE, "civstyle.airlift_to_always_enabled");
6865
6866 /* section: wonder_visibility */
6867 if (ok) {
6868 const char *text;
6869
6870 text = secfile_lookup_str_default(file,
6872 "wonder_visibility.small_wonders");
6873
6878 "Unknown wonder visibility type \"%s\"",
6879 text);
6880 ok = FALSE;
6881 }
6882 }
6883
6884 /* section: illness */
6887 "illness.illness_on");
6893 "illness.illness_base_factor");
6899 "illness.illness_min_size");
6905 "illness.illness_trade_infection");
6911 "illness.illness_pollution_factor");
6912
6913 /* section: incite_cost */
6919 "incite_cost.base_incite_cost");
6925 "incite_cost.improvement_factor");
6931 "incite_cost.unit_factor");
6937 "incite_cost.total_factor");
6938 }
6939
6940 if (ok) {
6941 const char *tus_text;
6942 int pharbor_default;
6943
6944 /* Section: combat_rules */
6947 "combat_rules.tired_attack");
6948
6951 "combat_rules.only_killing_makes_veteran");
6952
6955 "combat_rules.only_real_fight_makes_veteran");
6956
6959 "combat_rules.combat_odds_scaled_veterancy");
6960
6963 "combat_rules.damage_reduces_bombard_rate");
6964
6967 "combat_rules.low_firepower_badwallattacker");
6968
6969 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
6972 "combat_rules.low_firepower_pearl_harbour");
6973 } else {
6974 pharbor_default = 1;
6975 }
6976
6979 "combat_rules.low_firepower_pearl_harbor");
6980
6983 "combat_rules.low_firepower_combat_bonus");
6986 "combat_rules.low_firepower_nonnat_bombard");
6987
6992 "combat_rules.nuke_pop_loss_pct");
6993
6998 "combat_rules.nuke_defender_survival_chance_pct");
6999
7000 /* section: borders */
7006 "borders.radius_sq_city");
7012 "borders.size_effect");
7013
7019 "borders.radius_sq_city_permanent");
7020
7021 /* section: research */
7023 "research.tech_cost_style");
7028 "Unknown tech cost style \"%s\"",
7029 tus_text);
7030 ok = FALSE;
7031 }
7032
7034 "research.tech_leakage");
7039 "Unknown tech leakage \"%s\"",
7040 tus_text);
7041 ok = FALSE;
7042 }
7045 log_error("Only tech_leakage \"%s\" supported with "
7046 "tech_cost_style \"%s\". ",
7049 log_error("Switching to tech_leakage \"%s\".",
7052 }
7058 "research.base_tech_cost");
7059
7061 "research.tech_upkeep_style");
7062
7064
7067 "Unknown tech upkeep style \"%s\"",
7068 tus_text);
7069 ok = FALSE;
7070 }
7071 }
7072
7073 if (ok) {
7079 "research.tech_upkeep_divider");
7080
7081 sval = secfile_lookup_str_default(file, NULL, "research.free_tech_method");
7082 if (sval == NULL) {
7084 "No free_tech_method given");
7085 ok = FALSE;
7086 } else {
7090 "Bad value %s for free_tech_method.", sval);
7091 ok = FALSE;
7092 }
7093 }
7094 }
7095
7096 if (ok) {
7097 int cf;
7098
7099 /* section: culture */
7102 "culture.victory_min_points");
7105 "culture.victory_lead_pct");
7108 "culture.migration_pml");
7111 "culture.history_interest_pml");
7112
7113 /* section: world_peace */
7116 "world_peace.victory_turns");
7117
7118 /* section: calendar */
7121 "calendar.skip_year_0");
7124 "calendar.start_year");
7126 = secfile_lookup_int_default(file, 0, "calendar.fragments");
7127
7130 "Too many calendar fragments. Max is %d",
7132 ok = FALSE;
7134 }
7138 "calendar.positive_label"));
7142 "calendar.negative_label"));
7143
7144 for (cf = 0; cf < game.calendar.calendar_fragments; cf++) {
7145 const char *fname;
7146
7147 fname = secfile_lookup_str_default(file, NULL, "calendar.fragment_name%d", cf);
7148 if (fname != NULL) {
7151 }
7152 }
7153 }
7154
7155 if (ok) {
7156 /* section playercolors */
7157 struct rgbcolor *prgbcolor = NULL;
7158 bool color_read = TRUE;
7159
7160 /* Check if the player list is defined and empty. */
7161 if (playercolor_count() != 0) {
7162 ok = FALSE;
7163 } else {
7164 i = 0;
7165
7166 while (color_read) {
7167 prgbcolor = NULL;
7168
7169 color_read = rgbcolor_load(file, &prgbcolor, "playercolors.colorlist%d", i);
7170 if (color_read) {
7172 }
7173
7174 i++;
7175 }
7176
7177 if (playercolor_count() == 0) {
7178 ruleset_error(NULL, LOG_ERROR, "No player colors defined!");
7179 ok = FALSE;
7180 }
7181
7182 if (ok) {
7184 if (!rgbcolor_load(file, &game.plr_bg_color, "playercolors.background")) {
7186 "No background player color defined! (%s)",
7187 secfile_error());
7188 ok = FALSE;
7189 }
7190 }
7191 }
7192 }
7193
7194 if (ok) {
7195 /* section: teams */
7196 svec = secfile_lookup_str_vec(file, &teams, "teams.names");
7197 if (team_slot_count() < teams) {
7199 }
7201 for (i = 0; i < teams; i++) {
7203 }
7204 free(svec);
7205
7207 nval = (NULL != sec ? section_list_size(sec) : 0);
7208 if (nval > MAX_DISASTER_TYPES) {
7209 int num = nval; /* No "size_t" to printf */
7210
7212 "\"%s\": Too many disaster types (%d, max %d)",
7213 filename, num, MAX_DISASTER_TYPES);
7215 ok = FALSE;
7216 } else {
7218 }
7219 }
7220
7221 if (ok) {
7223 int id = disaster_index(pdis);
7224 int j;
7225 size_t eff_count;
7226 struct requirement_vector *reqs;
7227 const char *sec_name = section_name(section_list_get(sec, id));
7228
7229 if (!ruleset_load_names(&pdis->name, NULL, file, sec_name)) {
7231 "\"%s\": Cannot load disaster names",
7232 filename);
7233 ok = FALSE;
7234 break;
7235 }
7236
7238 if (reqs == NULL) {
7239 ok = FALSE;
7240 break;
7241 }
7243
7245 "%s.frequency", sec_name);
7246
7247 svec = secfile_lookup_str_vec(file, &eff_count, "%s.effects", sec_name);
7248
7249 BV_CLR_ALL(pdis->effects);
7250 for (j = 0; j < eff_count; j++) {
7251 const char *dsval = svec[j];
7253
7255
7258 "\"%s\" disaster \"%s\": unknown effect \"%s\".",
7259 filename, disaster_rule_name(pdis), dsval);
7260 ok = FALSE;
7261 break;
7262 } else {
7263 BV_SET(pdis->effects, effect);
7264 }
7265 }
7266
7267 free(svec);
7268
7269 if (!ok) {
7270 break;
7271 }
7274 }
7275
7276 if (ok) {
7278
7280 int id = achievement_index(pach);
7281 const char *sec_name = section_name(section_list_get(sec, id));
7282 const char *typename;
7283 const char *msg;
7284
7285 typename = secfile_lookup_str_default(file, NULL, "%s.type", sec_name);
7286
7287 pach->type = achievement_type_by_name(typename, fc_strcasecmp);
7288 if (!achievement_type_is_valid(pach->type)) {
7290 "Achievement has unknown type \"%s\".",
7291 typename != NULL ? typename : "(NULL)");
7292 ok = FALSE;
7293 }
7294
7295 if (ok) {
7297 "%s.unique", sec_name);
7298
7300 "%s.value", sec_name);
7301 pach->culture = secfile_lookup_int_default(file, 0,
7302 "%s.culture", sec_name);
7303
7304 msg = secfile_lookup_str_default(file, NULL, "%s.first_msg", sec_name);
7305 if (msg == NULL) {
7307 "Achievement %s has no first msg!", sec_name);
7308 ok = FALSE;
7309 } else {
7310 pach->first_msg = fc_strdup(msg);
7311 }
7312 }
7313
7314 if (ok) {
7315 msg = secfile_lookup_str_default(file, NULL, "%s.cons_msg", sec_name);
7316 if (msg == NULL) {
7317 if (!pach->unique) {
7319 "Achievement %s has no msg for consecutive gainers!",
7320 sec_name);
7321 ok = FALSE;
7322 }
7323 } else {
7324 pach->cons_msg = fc_strdup(msg);
7325 }
7326 }
7327
7328 if (!ok) {
7329 break;
7330 }
7333 }
7334
7335 if (ok) {
7336 for (i = 0; (name = secfile_lookup_str_default(file, NULL,
7337 "trade.settings%d.type",
7338 i)); i++) {
7340
7341 if (type == TRT_LAST) {
7343 "\"%s\" unknown trade route type \"%s\".",
7344 filename, name);
7345 ok = FALSE;
7346 } else {
7348 const char *cancelling;
7349 const char *bonus;
7350
7351 set->trade_pct = secfile_lookup_int_default(file, 100,
7352 "trade.settings%d.pct", i);
7353 cancelling = secfile_lookup_str_default(file, "Active",
7354 "trade.settings%d.cancelling", i);
7356 if (set->cancelling == TRI_LAST) {
7358 "\"%s\" unknown trade route cancelling type \"%s\".",
7359 filename, cancelling);
7360 ok = FALSE;
7361 }
7362
7363 bonus = secfile_lookup_str_default(file, "None", "trade.settings%d.bonus", i);
7364
7366
7369 "\"%s\" unknown trade route bonus type \"%s\".",
7370 filename, bonus);
7371 ok = FALSE;
7372 }
7373 }
7374 }
7375 }
7376
7377 if (ok) {
7378 const char *str;
7379
7381 = secfile_lookup_int_default(file, 0, "trade.min_trade_route_val");
7382
7385 "trade.reveal_trade_partner");
7386
7389 "trade.goods_selection");
7390
7392
7395 "\"%s\" goods selection method \"%s\" unknown.",
7396 filename, str);
7397 ok = FALSE;
7398 }
7399 }
7400
7401 if (ok) {
7403
7405 int id = goods_index(pgood);
7406 const char *sec_name = section_name(section_list_get(sec, id));
7407 struct requirement_vector *reqs;
7408 const char **slist;
7409 int j;
7410
7412 if (reqs == NULL) {
7413 ok = FALSE;
7414 break;
7415 }
7417
7418 pgood->from_pct = secfile_lookup_int_default(file, 100,
7419 "%s.from_pct", sec_name);
7420 pgood->to_pct = secfile_lookup_int_default(file, 100,
7421 "%s.to_pct", sec_name);
7422 pgood->onetime_pct = secfile_lookup_int_default(file, 100,
7423 "%s.onetime_pct", sec_name);
7424 pgood->select_priority = secfile_lookup_int_default(file, 1,
7425 "%s.select_priority", sec_name);
7426 pgood->replace_priority = secfile_lookup_int_default(file, 1,
7427 "%s.replace_priority", sec_name);
7428
7429 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
7430 BV_CLR_ALL(pgood->flags);
7431 for (j = 0; j < nval; j++) {
7432 enum goods_flag_id flag;
7433
7434 sval = slist[j];
7436 if (!goods_flag_id_is_valid(flag)) {
7437 ruleset_error(NULL, LOG_ERROR, "\"%s\" good \"%s\": unknown flag \"%s\".",
7438 filename, goods_rule_name(pgood), sval);
7439 ok = FALSE;
7440 break;
7441 } else {
7442 BV_SET(pgood->flags, flag);
7443 }
7444 }
7445 free(slist);
7446
7447 pgood->helptext = lookup_strvec(file, sec_name, "helptext");
7450 }
7451
7452 if (ok) {
7454
7455 if (sec != NULL) {
7456 int num = section_list_size(sec);
7457
7458 for (i = 0; i < num; i++) {
7459 const char *sec_name = section_name(section_list_get(sec, i));
7460 const char *clause_name = secfile_lookup_str_default(file, NULL,
7461 "%s.type", sec_name);
7463 struct clause_info *info;
7464 struct requirement_vector *reqs;
7465
7466 if (!clause_type_is_valid(type)) {
7468 "\"%s\" unknown clause type \"%s\".",
7469 filename, clause_name);
7470 ok = FALSE;
7471 break;
7472 }
7473
7474 info = clause_info_get(type);
7475
7476 if (info->enabled) {
7478 "\"%s\" duplicate clause type \"%s\" definition.",
7479 filename, clause_name);
7480 ok = FALSE;
7481 break;
7482 }
7483
7484 reqs = lookup_req_list(file, compat, sec_name, "giver_reqs", clause_name);
7485 if (reqs == NULL) {
7486 ok = FALSE;
7487 break;
7488 }
7490
7491 reqs = lookup_req_list(file, compat, sec_name, "receiver_reqs", clause_name);
7492 if (reqs == NULL) {
7493 ok = FALSE;
7494 break;
7495 }
7497
7498 reqs = lookup_req_list(file, compat, sec_name, "either_reqs", clause_name);
7499 if (reqs == NULL) {
7500 ok = FALSE;
7501 break;
7502 }
7504
7505 info->enabled = TRUE;
7506 }
7507 }
7509 }
7510
7511 if (ok) {
7513
7514 if (sec != NULL) {
7515 int num = section_list_size(sec);
7516 int curr;
7517
7518 for (curr = 0; curr < num; curr++) {
7519
7520 struct counter *pcount = counter_by_id(curr);
7521 const char *sec_name = section_name(section_list_get(sec, curr));
7522 const char *counter_type = secfile_lookup_str_default(file, NULL,
7523 "%s.type",
7524 sec_name);
7525
7528 if (!counter_behavior_is_valid(cb)) {
7530 "\"%s\" unknown counter type \"%s\".",
7531 filename, counter_type);
7532 ok = FALSE;
7533 break;
7534 }
7535
7536 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
7538 "\"%s\": Cannot load counter names",
7539 filename);
7540 ok = FALSE;
7541 break;
7542 }
7543
7544 pcount->helptext = lookup_strvec(file, sec_name, "helptext");
7545 pcount->type = cb;
7546 if (!secfile_lookup_int(file, &pcount->checkpoint,
7547 "%s.checkpoint", sec_name)) {
7548
7550 "\"%s\": No checkpoint value",
7551 filename);
7552 ok = FALSE;
7553 break;
7554 }
7555
7556 pcount->target = CTGT_CITY;
7557 pcount->index = curr;
7558 pcount->def = secfile_lookup_int_default(file, 0,
7559 "%s.def",
7560 sec_name);
7562 }
7563 }
7564 }
7565
7566 /* secfile_check_unused() is not here, but only after also settings section
7567 * has been loaded. */
7568
7569 return ok;
7570}
7571
7572/**********************************************************************/
7575static bool load_ruleset_actions(struct section_file *file,
7576 struct section_file *gamefile,
7577 struct rscompat_info *compat)
7578{
7579 bool ok = TRUE;
7580 const char *filename = secfile_name(file);
7581 struct section_list *sec;
7583 struct requirement_vector *reqs;
7584
7585 /* Auto attack. */
7586
7587 /* Action auto performers aren't ready to be exposed in the ruleset
7588 * yet. The behavior when two action auto performers for the same
7589 * cause can fire isn't set in stone yet. How is one of them chosen?
7590 * What if all the actions of the chosen action auto performer turned
7591 * out to be illegal but one of the other action auto performers that
7592 * fired has legal actions? These issues can decide what other action
7593 * rules action auto performers can represent in the future. Deciding
7594 * should therefore wait until a rule needs action auto performers to
7595 * work a certain way. */
7596 /* Only one action auto performer, ACTION_AUTO_MOVED_ADJ, is caused
7597 * by AAPC_UNIT_MOVED_ADJ. It is therefore safe to expose the full
7598 * requirement vector to the ruleset. */
7599
7600 /* A unit moved next to this unit and the autoattack server setting
7601 * is enabled. */
7604
7605 reqs = lookup_req_list(file, compat,
7606 "auto_attack", "if_attacker",
7607 "auto_attack");
7608 if (reqs == NULL) {
7609 ok = FALSE;
7610 } else {
7612
7614 "auto_attack.attack_actions",
7615 filename)) {
7616 /* Failed to load auto attack actions */
7618 "\"%s\": %s: failed load %s.",
7619 filename, "auto_attack", "attack_actions");
7620 ok = FALSE;
7621 }
7622 }
7623
7624 /* Section: actions */
7625 if (ok) {
7626 action_iterate(act_id) {
7627 struct action *paction = action_by_number(act_id);
7628
7629 if (!load_action_blocked_by_list(file, filename, paction, compat)) {
7630 ok = FALSE;
7631 break;
7632 }
7634
7635 if (ok) {
7636 if (!lookup_bv_actions(file, filename,
7638 "actions.diplchance_initial_odds")) {
7639 ok = FALSE;
7640 }
7641 }
7642
7643 if (ok) {
7644 /* If the "Poison City" action or the "Poison City Escape" action
7645 * should empty the granary. */
7646 /* TODO: empty granary and reduce population should become separate
7647 * action effect flags when actions are generalized. */
7651 "actions.poison_empties_food_stock");
7652
7653 /* If the "Steal Maps" action or the "Steal Maps Escape" action always
7654 * will reveal all cities when successful. */
7658 "actions.steal_maps_reveals_all_cities");
7659
7660 /* Allow setting certain properties for some actions before
7661 * generalized actions. */
7662 action_iterate(act_id) {
7663 if (!load_action_range(file, act_id)) {
7664 ok = FALSE;
7665 } else if (!load_action_kind(file, act_id)) {
7666 ok = FALSE;
7667 } else if (!load_action_actor_consuming_always(file, act_id)) {
7668 ok = FALSE;
7669 } else {
7670 const char *entry_name = NULL;
7671
7672 if (!action_id_is_internal(act_id)) {
7674 }
7675
7676 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
7678 }
7679 }
7680
7681 if (!ok) {
7682 break;
7683 }
7685 }
7686
7687 if (ok) {
7688 /* The quiet (don't auto generate help for) property of all actions
7689 * live in a single enum vector. This avoids generic action
7690 * expectations. */
7691 if (secfile_entry_by_path(file, "actions.quiet_actions")) {
7693 size_t asize;
7694 int j;
7695
7698 "actions.quiet_actions");
7699
7700 if (!quiet_actions) {
7701 /* Entity exists but couldn't read it. */
7703 "\"%s\": actions.quiet_actions: bad action list",
7704 filename);
7705
7706 ok = FALSE;
7707 } else {
7708 for (j = 0; j < asize; j++) {
7709 /* Don't auto generate help text for this action. */
7711 }
7712
7714 }
7715 }
7716 }
7717
7718 if (ok) {
7719 /* Hard code action sub results for now. */
7720
7721 /* Unit Enter Hut */
7723 BV_SET(paction->sub_results, ACT_SUB_RES_HUT_ENTER);
7733
7734 /* Unit Frighten Hut */
7746
7747 /* Unit May Embark */
7748 action_iterate(act_id) {
7749 struct action *paction = action_by_number(act_id);
7750
7752 "civstyle.paradrop_to_transport")
7755 BV_SET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK);
7756 }
7757
7758 /* Embark actions will always embark, not maybe embark. */
7760
7761 /* Non Lethal bombard */
7768 }
7769 }
7770
7771 if (ok) {
7772 /* Forced actions after another action was successfully performed. */
7773
7774 if (!load_action_post_success_force(file, filename,
7778 ok = FALSE;
7779 } else if (!load_action_post_success_force(file, filename,
7783 ok = FALSE;
7784 } else if (!load_action_post_success_force(file, filename,
7787 ACTION_ATTACK))) {
7788 ok = FALSE;
7789 } else if (!load_action_post_success_force(file, filename,
7792 ACTION_ATTACK2))) {
7793 ok = FALSE;
7794 } else if (!load_action_post_success_force(file, filename,
7798 ok = FALSE;
7799 } else if (!load_action_post_success_force(file, filename,
7803 ok = FALSE;
7804 }
7805
7806 /* No "Suicide Attack". Can't act when dead. */
7807 }
7808
7809 if (ok) {
7810 /* The city that made the unit's current tile native is gone.
7811 * Evaluated against an adjacent tile. */
7813 auto_perf->cause = AAPC_CITY_GONE;
7814
7815 /* I have no objections to moving this out of game's actions to
7816 * cities.ruleset, units.ruleset or an other location in game.ruleset
7817 * you find more suitable. -- Sveinung */
7819 "actions.escape_city", filename)) {
7820 ok = FALSE;
7821 }
7822 }
7823
7824 if (ok) {
7825 /* The unit's stack has been defeated and is scheduled for execution
7826 * but the unit has the CanEscape unit type flag.
7827 * Evaluated against an adjacent tile. */
7830
7831 /* I have no objections to moving this out of game's actions to
7832 * cities.ruleset, units.ruleset or an other location in game.ruleset
7833 * you find more suitable. -- Sveinung */
7835 "actions.unit_stack_death", filename)) {
7836 ok = FALSE;
7837 }
7838 }
7839
7840 if (ok) {
7842 if (sec != nullptr) {
7843 section_list_iterate(sec, psection) {
7844 const char *sec_name = section_name(psection);
7845 const char *action_text;
7846 struct action *paction;
7847 const char *ui_name;
7848
7849 action_text = secfile_lookup_str(file, "%s.action", sec_name);
7850
7851 if (action_text == nullptr) {
7852 ruleset_error(nullptr, LOG_ERROR,
7853 "\"%s\" [%s] missing action to configure.",
7854 filename, sec_name);
7855 ok = FALSE;
7856 break;
7857 }
7858
7860 if (paction == nullptr) {
7861 ruleset_error(nullptr, LOG_ERROR,
7862 "\"%s\" [%s] lists unknown action type \"%s\".",
7863 filename, sec_name, action_text);
7864 ok = FALSE;
7865 break;
7866 }
7867
7868 if (paction->configured) {
7869 ruleset_error(nullptr, LOG_ERROR,
7870 "\"%s\" [%s] duplicate configuration for action \"%s\".",
7871 filename, sec_name, action_text);
7872 ok = FALSE;
7873 break;
7874 }
7875
7876 paction->configured = TRUE;
7877
7878 ui_name = secfile_lookup_str_default(file, nullptr,
7879 "%s.ui_name", sec_name);
7880 if (ui_name == nullptr) {
7882 }
7883 sz_strlcpy(paction->ui_name, ui_name);
7885 }
7886 }
7887
7888 if (ok) {
7889 action_iterate(act) {
7890 struct action *paction = action_by_number(act);
7891
7892 if (!paction->configured) {
7894 }
7896 }
7897
7898 if (ok) {
7900
7901 if (sec == nullptr && compat->compat_mode && compat->version < RSFORMAT_3_3) {
7904 }
7905
7906 if (sec != nullptr) {
7907 section_list_iterate(sec, psection) {
7908 struct action_enabler *enabler;
7909 const char *sec_name = section_name(psection);
7910 struct action *paction;
7911 struct requirement_vector *actor_reqs;
7912 struct requirement_vector *target_reqs;
7913 const char *action_text;
7914 const char *comment;
7915
7917
7918 action_text = secfile_lookup_str(file, "%s.action", sec_name);
7919
7920 if (action_text == nullptr) {
7921 ruleset_error(nullptr, LOG_ERROR,
7922 "\"%s\" [%s] missing action to enable.",
7923 filename, sec_name);
7924 ok = FALSE;
7925 break;
7926 }
7927
7929 if (paction == nullptr) {
7930 ruleset_error(nullptr, LOG_ERROR,
7931 "\"%s\" [%s] lists unknown action type \"%s\".",
7932 filename, sec_name, action_text);
7933 ok = FALSE;
7934 break;
7935 }
7936
7937 enabler->action = action_id(paction);
7938
7939 actor_reqs = lookup_req_list(file, compat, sec_name, "actor_reqs", action_text);
7940 if (actor_reqs == NULL) {
7941 ok = FALSE;
7942 break;
7943 }
7944
7945 requirement_vector_copy(&enabler->actor_reqs, actor_reqs);
7946
7947 target_reqs = lookup_req_list(file, compat, sec_name, "target_reqs", action_text);
7948 if (target_reqs == NULL) {
7949 ok = FALSE;
7950 break;
7951 }
7952
7953 requirement_vector_copy(&enabler->target_reqs, target_reqs);
7954
7955 comment = secfile_lookup_str(file, "%s.comment", sec_name);
7956 if (comment != nullptr) {
7957 enabler->rulesave.comment = fc_strdup(comment);
7958 }
7959
7962
7964 }
7965 }
7966
7967 return ok;
7968}
7969
7970/**********************************************************************/
7974static void send_ruleset_unit_classes(struct conn_list *dest)
7975{
7976 struct packet_ruleset_unit_class packet;
7978 int i;
7979
7980 for (i = 0; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
7981 const char *flagname;
7982 const char *helptxt;
7983
7985
7987 if (flagname == NULL) {
7988 fpacket.name[0] = '\0';
7989 } else {
7991 }
7992
7994 if (helptxt == NULL) {
7995 fpacket.helptxt[0] = '\0';
7996 } else {
7997 sz_strlcpy(fpacket.helptxt, helptxt);
7998 }
7999
8001 }
8002
8004 packet.id = uclass_number(c);
8005 sz_strlcpy(packet.name, untranslated_name(&c->name));
8006 sz_strlcpy(packet.rule_name, rule_name_get(&c->name));
8007 packet.min_speed = c->min_speed;
8008 packet.hp_loss_pct = c->hp_loss_pct;
8009 packet.non_native_def_pct = c->non_native_def_pct;
8010 packet.flags = c->flags;
8011
8012 PACKET_STRVEC_INSERT(packet.helptext, c->helptext);
8013
8014 lsend_packet_ruleset_unit_class(dest, &packet);
8016}
8017
8018/**********************************************************************/
8022static void send_ruleset_units(struct conn_list *dest)
8023{
8024 struct packet_ruleset_unit packet;
8025#ifdef FREECIV_WEB
8027#endif /* FREECIV_WEB */
8029 int i;
8030
8031 for (i = 0; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
8032 const char *flagname;
8033 const char *helptxt;
8034
8036
8038 if (flagname == NULL) {
8039 fpacket.name[0] = '\0';
8040 } else {
8042 }
8043
8045 if (helptxt == NULL) {
8046 fpacket.helptxt[0] = '\0';
8047 } else {
8048 sz_strlcpy(fpacket.helptxt, helptxt);
8049 }
8050
8052 }
8053
8055 packet.id = utype_number(u);
8056 sz_strlcpy(packet.name, untranslated_name(&u->name));
8057 sz_strlcpy(packet.rule_name, rule_name_get(&u->name));
8058 sz_strlcpy(packet.sound_move, u->sound_move);
8059 sz_strlcpy(packet.sound_move_alt, u->sound_move_alt);
8060 sz_strlcpy(packet.sound_fight, u->sound_fight);
8061 sz_strlcpy(packet.sound_fight_alt, u->sound_fight_alt);
8062 sz_strlcpy(packet.graphic_str, u->graphic_str);
8063 sz_strlcpy(packet.graphic_alt, u->graphic_alt);
8064 sz_strlcpy(packet.graphic_alt2, u->graphic_alt2);
8066 packet.build_cost = u->build_cost;
8067 packet.pop_cost = u->pop_cost;
8068 packet.attack_strength = u->attack_strength;
8069 packet.defense_strength = u->defense_strength;
8070 packet.move_rate = u->move_rate;
8071
8072 /* Shallow-copy (borrow) requirement vector */
8073 packet.build_reqs = u->build_reqs;
8074
8075 packet.vision_radius_sq = u->vision_radius_sq;
8076 packet.transport_capacity = u->transport_capacity;
8077 packet.hp = u->hp;
8078 packet.firepower = u->firepower;
8079 packet.obsoleted_by = u->obsoleted_by
8080 ? utype_number(u->obsoleted_by)
8081 : utype_count();
8082 packet.converted_to = u->converted_to
8083 ? utype_number(u->converted_to)
8084 : utype_count();
8085 packet.convert_time = u->convert_time;
8086 packet.fuel = u->fuel;
8087 packet.flags = u->flags;
8088 packet.roles = u->roles;
8089 packet.happy_cost = u->happy_cost;
8091 packet.upkeep[o] = u->upkeep[o];
8093 packet.paratroopers_range = u->paratroopers_range;
8094 packet.bombard_rate = u->bombard_rate;
8095 packet.city_size = u->city_size;
8096 packet.city_slots = u->city_slots;
8097 packet.tp_defense = u->tp_defense;
8098 packet.cargo = u->cargo;
8099 packet.targets = u->targets;
8100 packet.embarks = u->embarks;
8101 packet.disembarks = u->disembarks;
8102 packet.vlayer = u->vlayer;
8103
8104 if (u->veteran == NULL) {
8105 /* Use the default veteran system. */
8106 packet.veteran_levels = 0;
8107 } else {
8108 /* Per unit veteran system definition. */
8110
8111 for (i = 0; i < packet.veteran_levels; i++) {
8112 const struct veteran_level *vlevel = utype_veteran_level(u, i);
8113
8115 packet.power_fact[i] = vlevel->power_fact;
8116 packet.move_bonus[i] = vlevel->move_bonus;
8117 packet.base_raise_chance[i] = vlevel->base_raise_chance;
8118 packet.work_raise_chance[i] = vlevel->work_raise_chance;
8119 }
8120 }
8121 PACKET_STRVEC_INSERT(packet.helptext, u->helptext);
8122
8123 packet.worker = u->adv.worker;
8124
8125#ifdef FREECIV_WEB
8126 web_packet.id = utype_number(u);
8127
8128 BV_CLR_ALL(web_packet.utype_actions);
8129
8130 action_iterate(act) {
8131 if (utype_can_do_action(u, act)) {
8132 BV_SET(web_packet.utype_actions, act);
8133 }
8135#endif /* FREECIV_WEB */
8136
8137 lsend_packet_ruleset_unit(dest, &packet);
8139
8140 combat_bonus_list_iterate(u->bonuses, pbonus) {
8142
8143 bonuspacket.unit = packet.id;
8144 bonuspacket.flag = pbonus->flag;
8145 bonuspacket.type = pbonus->type;
8146 bonuspacket.value = pbonus->value;
8147 bonuspacket.quiet = pbonus->quiet;
8148
8152}
8153
8154/**********************************************************************/
8158static void send_ruleset_specialists(struct conn_list *dest)
8159{
8160 struct packet_ruleset_specialist packet;
8161
8164
8165 packet.id = spec_id;
8167 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
8171
8172 /* Shallow-copy (borrow) requirement vector */
8173 packet.reqs = s->reqs;
8174
8176
8177 lsend_packet_ruleset_specialist(dest, &packet);
8179}
8180/**********************************************************************/
8183static void send_ruleset_tech_classes(struct conn_list *dest)
8184{
8185 struct packet_ruleset_tech_class packet;
8186
8188 packet.id = ptclass->idx;
8189 sz_strlcpy(packet.name, untranslated_name(&ptclass->name));
8190 sz_strlcpy(packet.rule_name, rule_name_get(&ptclass->name));
8191 packet.cost_pct = ptclass->cost_pct;
8192
8193 lsend_packet_ruleset_tech_class(dest, &packet);
8195}
8196
8197/**********************************************************************/
8201static void send_ruleset_techs(struct conn_list *dest)
8202{
8203 struct packet_ruleset_tech packet;
8205 int i;
8206
8207 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
8208 const char *flagname;
8209 const char *helptxt;
8210
8211 fpacket.id = i + TECH_USER_1;
8212
8214 if (flagname == NULL) {
8215 fpacket.name[0] = '\0';
8216 } else {
8218 }
8219
8221 if (helptxt == NULL) {
8222 fpacket.helptxt[0] = '\0';
8223 } else {
8224 sz_strlcpy(fpacket.helptxt, helptxt);
8225 }
8226
8228 }
8229
8230 /* Since we have to prepend the tech requirements to the requirement
8231 * vector, we need to initialize a separate vector and deep-copy the
8232 * other requirements into it. */
8234
8235 advance_iterate(a) {
8236 packet.id = advance_number(a);
8237 packet.removed = !valid_advance(a);
8238 if (a->tclass == NULL) {
8239 packet.tclass = 0;
8240 } else {
8241 packet.tclass = a->tclass->idx;
8242 }
8243 sz_strlcpy(packet.name, untranslated_name(&a->name));
8244 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8245 sz_strlcpy(packet.graphic_str, a->graphic_str);
8246 sz_strlcpy(packet.graphic_alt, a->graphic_alt);
8247
8248 /* Reset requirement vector. */
8250
8251 /* The requirements req1 and req2 are needed to research a tech. Send
8252 * them in the research_reqs requirement vector. Range is set to player
8253 * since pooled research is configurable. */
8254
8255 if ((a->require[AR_ONE] != A_NEVER)
8256 && advance_number(a->require[AR_ONE]) > A_NONE) {
8257 struct requirement req
8259 FALSE, TRUE, FALSE,
8260 advance_number(a->require[AR_ONE]));
8262 }
8263
8264 if ((a->require[AR_TWO] != A_NEVER)
8265 && advance_number(a->require[AR_TWO]) > A_NONE) {
8266 struct requirement req
8268 FALSE, TRUE, FALSE,
8269 advance_number(a->require[AR_TWO]));
8271 }
8272
8273 /* The requirements of the tech's research_reqs also goes in the
8274 * packet's research_reqs requirement vector. */
8275 requirement_vector_iterate(&a->research_reqs, req) {
8278
8279 packet.root_req = a->require[AR_ROOT]
8280 ? advance_number(a->require[AR_ROOT])
8281 : advance_count();
8282
8283 packet.flags = a->flags;
8284 packet.cost = a->cost;
8285 packet.num_reqs = a->num_reqs;
8286 PACKET_STRVEC_INSERT(packet.helptext, a->helptext);
8287
8288 lsend_packet_ruleset_tech(dest, &packet);
8290
8292}
8293
8294/**********************************************************************/
8297static void send_ruleset_counters(struct conn_list *dest)
8298{
8300 struct packet_ruleset_counter packet;
8301
8302 sz_strlcpy(packet.name, untranslated_name(&pcount->name));
8303 sz_strlcpy(packet.rule_name, rule_name_get(&pcount->name));
8304 packet.checkpoint = pcount->checkpoint;
8305 packet.behavior = pcount->type;
8306 packet.type = pcount->target;
8307 packet.def = pcount->def;
8308
8309 PACKET_STRVEC_INSERT(packet.helptext, pcount->helptext);
8310 lsend_packet_ruleset_counter(dest, &packet);
8312}
8313
8314/**********************************************************************/
8318static void send_ruleset_buildings(struct conn_list *dest)
8319{
8320 int i;
8321
8322 for (i = 0; i < MAX_NUM_USER_BUILDING_FLAGS; i++) {
8324 const char *flagname;
8325 const char *helptxt;
8326
8328
8330 if (flagname == NULL) {
8331 fpacket.name[0] = '\0';
8332 } else {
8334 }
8335
8337 if (helptxt == NULL) {
8338 fpacket.helptxt[0] = '\0';
8339 } else {
8340 sz_strlcpy(fpacket.helptxt, helptxt);
8341 }
8342
8344 }
8345
8347 struct packet_ruleset_building packet;
8348
8349 packet.id = improvement_number(b);
8350 packet.genus = b->genus;
8351 sz_strlcpy(packet.name, untranslated_name(&b->name));
8352 sz_strlcpy(packet.rule_name, rule_name_get(&b->name));
8353 sz_strlcpy(packet.graphic_str, b->graphic_str);
8354 sz_strlcpy(packet.graphic_alt, b->graphic_alt);
8355 sz_strlcpy(packet.graphic_alt2, b->graphic_alt2);
8356
8357 /* Shallow-copy (borrow) requirement vectors */
8358 packet.reqs = b->reqs;
8359 packet.obs_reqs = b->obsolete_by;
8360
8361 packet.build_cost = b->build_cost;
8362 packet.upkeep = b->upkeep;
8363 packet.sabotage = b->sabotage;
8364 packet.flags = b->flags;
8365 sz_strlcpy(packet.soundtag, b->soundtag);
8366 sz_strlcpy(packet.soundtag_alt, b->soundtag_alt);
8367 sz_strlcpy(packet.soundtag_alt2, b->soundtag_alt2);
8368 PACKET_STRVEC_INSERT(packet.helptext, b->helptext);
8369
8370 lsend_packet_ruleset_building(dest, &packet);
8372}
8373
8374/**********************************************************************/
8378static void send_ruleset_terrain(struct conn_list *dest)
8379{
8380 struct packet_ruleset_terrain packet;
8382 int i;
8383
8385
8386 for (i = 0; i < MAX_NUM_USER_TER_FLAGS; i++) {
8387 const char *flagname;
8388 const char *helptxt;
8389
8390 fpacket.id = i + TER_USER_1;
8391
8393 if (flagname == NULL) {
8394 fpacket.name[0] = '\0';
8395 } else {
8397 }
8398
8400 if (helptxt == NULL) {
8401 fpacket.helptxt[0] = '\0';
8402 } else {
8403 sz_strlcpy(fpacket.helptxt, helptxt);
8404 }
8405
8407 }
8408
8409 terrain_type_iterate(pterrain) {
8410 packet.id = terrain_number(pterrain);
8411 packet.tclass = pterrain->tclass;
8412 packet.native_to = pterrain->native_to;
8413
8414 sz_strlcpy(packet.name, untranslated_name(&pterrain->name));
8415 sz_strlcpy(packet.rule_name, rule_name_get(&pterrain->name));
8416 sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
8417 sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
8418 sz_strlcpy(packet.graphic_alt2, pterrain->graphic_alt2);
8419
8420 packet.movement_cost = pterrain->movement_cost;
8421 packet.defense_bonus = pterrain->defense_bonus;
8422
8424 packet.output[o] = pterrain->output[o];
8426
8427 packet.num_resources = 0;
8428 terrain_resources_iterate(pterrain, res, freq) {
8429 packet.resources[packet.num_resources] = extra_number(res);
8430 packet.resource_freq[packet.num_resources] = freq;
8431 packet.num_resources++;
8433
8435 packet.road_output_incr_pct[o] = pterrain->road_output_incr_pct[o];
8437
8438 packet.base_time = pterrain->base_time;
8439 packet.road_time = pterrain->road_time;
8440
8441 packet.cultivate_result = (pterrain->cultivate_result
8442 ? terrain_number(pterrain->cultivate_result)
8443 : terrain_count());
8444 packet.cultivate_time = pterrain->cultivate_time;
8445
8446 packet.plant_result = (pterrain->plant_result
8447 ? terrain_number(pterrain->plant_result)
8448 : terrain_count());
8449 packet.plant_time = pterrain->plant_time;
8450
8451 packet.irrigation_food_incr = pterrain->irrigation_food_incr;
8452 packet.irrigation_time = pterrain->irrigation_time;
8453
8454 packet.mining_shield_incr = pterrain->mining_shield_incr;
8455 packet.mining_time = pterrain->mining_time;
8456
8457 packet.animal = (pterrain->animal == NULL ? -1 : utype_number(pterrain->animal));
8458 packet.transform_result = (pterrain->transform_result
8459 ? terrain_number(pterrain->transform_result)
8460 : terrain_count());
8461 packet.placing_time = pterrain->placing_time;
8462 packet.pillage_time = pterrain->pillage_time;
8463 packet.transform_time = pterrain->transform_time;
8464
8466 for (i = 0; i < game.control.num_extra_types; i++) {
8467 packet.extra_removal_times[i] = pterrain->extra_removal_times[i];
8468 }
8469
8470 packet.flags = pterrain->flags;
8471
8472 packet.color_red = pterrain->rgb->r;
8473 packet.color_green = pterrain->rgb->g;
8474 packet.color_blue = pterrain->rgb->b;
8475
8476 PACKET_STRVEC_INSERT(packet.helptext, pterrain->helptext);
8477
8478 lsend_packet_ruleset_terrain(dest, &packet);
8480}
8481
8482/**********************************************************************/
8485static void send_ruleset_resources(struct conn_list *dest)
8486{
8487 struct packet_ruleset_resource packet;
8488
8490 packet.id = extra_index(presource);
8491
8493 packet.output[o] = presource->data.resource->output[o];
8495
8496 lsend_packet_ruleset_resource(dest, &packet);
8498}
8499
8500/**********************************************************************/
8504static void send_ruleset_extras(struct conn_list *dest)
8505{
8506 int i;
8507
8508 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
8510 const char *flagname;
8511 const char *helptxt;
8512
8514
8516 if (flagname == NULL) {
8517 fpacket.name[0] = '\0';
8518 } else {
8520 }
8521
8523 if (helptxt == NULL) {
8524 fpacket.helptxt[0] = '\0';
8525 } else {
8526 sz_strlcpy(fpacket.helptxt, helptxt);
8527 }
8528
8530 }
8531
8533 struct packet_ruleset_extra packet;
8534 int j;
8535
8536 packet.id = extra_number(e);
8537 sz_strlcpy(packet.name, untranslated_name(&e->name));
8538 sz_strlcpy(packet.rule_name, rule_name_get(&e->name));
8539
8540 packet.category = e->category;
8541
8542 BV_CLR_ALL(packet.causes);
8543 for (j = 0; j < EC_COUNT; j++) {
8544 if (is_extra_caused_by(e, j)) {
8545 BV_SET(packet.causes, j);
8546 }
8547 }
8548
8549 BV_CLR_ALL(packet.rmcauses);
8550 for (j = 0; j < ERM_COUNT; j++) {
8551 if (is_extra_removed_by(e, j)) {
8552 BV_SET(packet.rmcauses, j);
8553 }
8554 }
8555
8556 sz_strlcpy(packet.activity_gfx, e->activity_gfx);
8557 sz_strlcpy(packet.act_gfx_alt, e->act_gfx_alt);
8558 sz_strlcpy(packet.act_gfx_alt2, e->act_gfx_alt2);
8559 sz_strlcpy(packet.rmact_gfx, e->rmact_gfx);
8560 sz_strlcpy(packet.rmact_gfx_alt, e->rmact_gfx_alt);
8561 sz_strlcpy(packet.rmact_gfx_alt2, e->rmact_gfx_alt2);
8562 sz_strlcpy(packet.graphic_str, e->graphic_str);
8563 sz_strlcpy(packet.graphic_alt, e->graphic_alt);
8564
8565 /* Shallow-copy (borrow) requirement vectors */
8566 packet.reqs = e->reqs;
8567 packet.rmreqs = e->rmreqs;
8568
8569 packet.appearance_chance = e->appearance_chance;
8570 /* Shallow-copy (borrow) requirement vector */
8571 packet.appearance_reqs = e->appearance_reqs;
8572
8573 packet.disappearance_chance = e->disappearance_chance;
8574 /* Shallow-copy (borrow) requirement vector */
8575 packet.disappearance_reqs = e->disappearance_reqs;
8576
8577 packet.visibility_req = e->visibility_req;
8578 packet.buildable = e->buildable;
8579 packet.generated = e->generated;
8580 packet.build_time = e->build_time;
8581 packet.build_time_factor = e->build_time_factor;
8582 packet.removal_time = e->removal_time;
8583 packet.removal_time_factor = e->removal_time_factor;
8584 packet.infracost = e->infracost;
8585 packet.defense_bonus = e->defense_bonus;
8586 packet.eus = e->eus;
8587 packet.no_aggr_near_city = e->no_aggr_near_city;
8588
8589 packet.native_to = e->native_to;
8590
8591 packet.flags = e->flags;
8592 packet.hidden_by = e->hidden_by;
8593 packet.bridged_over = e->bridged_over;
8594 packet.conflicts = e->conflicts;
8595
8596 PACKET_STRVEC_INSERT(packet.helptext, e->helptext);
8597
8598 lsend_packet_ruleset_extra(dest, &packet);
8600}
8601
8602/**********************************************************************/
8606static void send_ruleset_bases(struct conn_list *dest)
8607{
8609 struct base_type *b = extra_base_get(pextra);
8610 struct packet_ruleset_base packet;
8611
8612 packet.id = base_number(b);
8613
8614 packet.gui_type = b->gui_type;
8615 packet.border_sq = b->border_sq;
8616 packet.vision_main_sq = b->vision_main_sq;
8617 packet.vision_invis_sq = b->vision_invis_sq;
8618 packet.vision_subs_sq = b->vision_subs_sq;
8619
8620 lsend_packet_ruleset_base(dest, &packet);
8622}
8623
8624/**********************************************************************/
8628static void send_ruleset_roads(struct conn_list *dest)
8629{
8630 struct packet_ruleset_road packet;
8631
8633 struct road_type *r = extra_road_get(pextra);
8634
8635 packet.id = road_number(r);
8636
8637 packet.gui_type = r->gui_type;
8638
8639 /* Shallow-copy (borrow) requirement vector */
8640 packet.first_reqs = r->first_reqs;
8641
8642 packet.move_cost = r->move_cost;
8643 packet.move_mode = r->move_mode;
8644
8646 packet.tile_incr_const[o] = r->tile_incr_const[o];
8647 packet.tile_incr[o] = r->tile_incr[o];
8648 packet.tile_bonus[o] = r->tile_bonus[o];
8650
8651 packet.compat = r->compat;
8652
8653 packet.integrates = r->integrates;
8654 packet.flags = r->flags;
8655
8656 lsend_packet_ruleset_road(dest, &packet);
8658}
8659
8660/**********************************************************************/
8664static void send_ruleset_goods(struct conn_list *dest)
8665{
8666 struct packet_ruleset_goods packet;
8667
8669 packet.id = goods_number(g);
8670 sz_strlcpy(packet.name, untranslated_name(&g->name));
8671 sz_strlcpy(packet.rule_name, rule_name_get(&g->name));
8672
8673 /* Shallow-copy (borrow) requirement vector */
8674 packet.reqs = g->reqs;
8675
8676 packet.from_pct = g->from_pct;
8677 packet.to_pct = g->to_pct;
8678 packet.onetime_pct = g->onetime_pct;
8679 packet.select_priority = g->select_priority;
8680 packet.replace_priority = g->replace_priority;
8681 packet.flags = g->flags;
8682
8683 PACKET_STRVEC_INSERT(packet.helptext, g->helptext);
8684
8685 lsend_packet_ruleset_goods(dest, &packet);
8687}
8688
8689/**********************************************************************/
8693static void send_ruleset_disasters(struct conn_list *dest)
8694{
8695 struct packet_ruleset_disaster packet;
8696
8698 packet.id = disaster_number(d);
8699
8700 sz_strlcpy(packet.name, untranslated_name(&d->name));
8701 sz_strlcpy(packet.rule_name, rule_name_get(&d->name));
8702
8703 /* Shallow-copy (borrow) requirement vector */
8704 packet.reqs = d->reqs;
8705
8706 packet.frequency = d->frequency;
8707
8708 packet.effects = d->effects;
8709
8710 lsend_packet_ruleset_disaster(dest, &packet);
8712}
8713
8714/**********************************************************************/
8718static void send_ruleset_achievements(struct conn_list *dest)
8719{
8720 struct packet_ruleset_achievement packet;
8721
8723 packet.id = achievement_number(a);
8724
8725 sz_strlcpy(packet.name, untranslated_name(&a->name));
8726 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8727
8728 packet.type = a->type;
8729 packet.unique = a->unique;
8730 packet.value = a->value;
8731
8732 lsend_packet_ruleset_achievement(dest, &packet);
8734}
8735
8736/**********************************************************************/
8739static void send_ruleset_actions(struct conn_list *dest)
8740{
8741 struct packet_ruleset_action packet;
8742
8743 action_iterate(act) {
8744 struct action *paction = action_by_number(act);
8745
8746 packet.id = act;
8748 packet.quiet = action_by_number(act)->quiet;
8749
8750 packet.result = paction->result;
8751 packet.sub_results = paction->sub_results;
8752 packet.actor_consuming_always = paction->actor_consuming_always;
8753
8754 packet.act_kind = action_by_number(act)->actor_kind;
8755 packet.tgt_kind = action_by_number(act)->target_kind;
8757
8760 packet.blocked_by = action_by_number(act)->blocked_by;
8761
8762 lsend_packet_ruleset_action(dest, &packet);
8764}
8765
8766/**********************************************************************/
8770{
8771 struct packet_ruleset_action_enabler packet;
8772
8775
8776 /* Shallow-copy (borrow) requirement vectors */
8777 packet.actor_reqs = enabler->actor_reqs;
8778 packet.target_reqs = enabler->target_reqs;
8779
8782}
8783
8784/**********************************************************************/
8789{
8790 int counter;
8791 int id;
8792 struct packet_ruleset_action_auto packet;
8793
8794 id = 0;
8796 packet.id = id++;
8797
8798 packet.cause = aperf->cause;
8799
8800 /* Shallow-copy (borrow) requirement vector */
8801 packet.reqs = aperf->reqs;
8802
8803 for (counter = 0;
8804 /* Can't list more actions than all actions. */
8806 /* ACTION_NONE terminates the list. */
8807 && aperf->alternatives[counter] != ACTION_NONE;
8808 counter++) {
8809 packet.alternatives[counter] = aperf->alternatives[counter];
8810 }
8811 packet.alternatives_count = counter;
8812
8813 lsend_packet_ruleset_action_auto(dest, &packet);
8815}
8816
8817/**********************************************************************/
8821static void send_ruleset_trade_routes(struct conn_list *dest)
8822{
8823 struct packet_ruleset_trade packet;
8825
8826 for (type = TRT_NATIONAL; type < TRT_LAST; type++) {
8828
8829 packet.id = type;
8830 packet.trade_pct = set->trade_pct;
8831 packet.cancelling = set->cancelling;
8832 packet.bonus_type = set->bonus_type;
8833
8834 lsend_packet_ruleset_trade(dest, &packet);
8835 }
8836}
8837
8838/**********************************************************************/
8842static void send_ruleset_governments(struct conn_list *dest)
8843{
8844 struct packet_ruleset_government gov;
8846
8848 /* Send one packet_government */
8849 gov.id = government_number(g);
8850
8851 /* Shallow-copy (borrow) requirement vector */
8852 gov.reqs = g->reqs;
8853
8854 sz_strlcpy(gov.name, untranslated_name(&g->name));
8855 sz_strlcpy(gov.rule_name, rule_name_get(&g->name));
8856 sz_strlcpy(gov.graphic_str, g->graphic_str);
8857 sz_strlcpy(gov.graphic_alt, g->graphic_alt);
8858 sz_strlcpy(gov.sound_str, g->sound_str);
8859 sz_strlcpy(gov.sound_alt, g->sound_alt);
8860 sz_strlcpy(gov.sound_alt2, g->sound_alt2);
8861 PACKET_STRVEC_INSERT(gov.helptext, g->helptext);
8862
8864
8865 /* Send one packet_government_ruler_title per ruler title. */
8867 const struct nation_type *pnation = ruler_title_nation(pruler_title);
8868
8869 title.gov = government_number(g);
8870 title.nation = pnation ? nation_number(pnation) : nation_count();
8871 sz_strlcpy(title.male_title,
8873 sz_strlcpy(title.female_title,
8878}
8879
8880/**********************************************************************/
8884static void send_ruleset_nations(struct conn_list *dest)
8885{
8888 struct packet_ruleset_nation packet;
8889 int i;
8890
8892 i = 0;
8897 i++;
8900
8902 i = 0;
8904 sz_strlcpy(groups_packet.groups[i],
8906 groups_packet.hidden[i] = pgroup->hidden;
8907 i++;
8910
8912 packet.id = nation_number(n);
8913 if (n->translation_domain == NULL) {
8914 packet.translation_domain[0] = '\0';
8915 } else {
8916 sz_strlcpy(packet.translation_domain, n->translation_domain);
8917 }
8918 sz_strlcpy(packet.adjective, untranslated_name(&n->adjective));
8919 sz_strlcpy(packet.rule_name, rule_name_get(&n->adjective));
8920 sz_strlcpy(packet.noun_plural, untranslated_name(&n->noun_plural));
8921 sz_strlcpy(packet.graphic_str, n->flag_graphic_str);
8922 sz_strlcpy(packet.graphic_alt, n->flag_graphic_alt);
8923
8924 i = 0;
8928 i++;
8930 packet.leader_count = i;
8931
8932 packet.style = style_number(n->style);
8933 packet.is_playable = n->is_playable;
8934 packet.barbarian_type = n->barb_type;
8935
8936 sz_strlcpy(packet.legend, n->legend);
8937
8938 i = 0;
8940 packet.sets[i++] = nation_set_number(pset);
8942 packet.nsets = i;
8943
8944 i = 0;
8946 packet.groups[i++] = nation_group_number(pgroup);
8948 packet.ngroups = i;
8949
8950 packet.init_government_id = n->init_government
8951 ? government_number(n->init_government) : government_count();
8952 fc_assert(ARRAY_SIZE(packet.init_techs) == ARRAY_SIZE(n->init_techs));
8953 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
8954 if (n->init_techs[i] != A_LAST) {
8955 packet.init_techs[i] = n->init_techs[i];
8956 } else {
8957 break;
8958 }
8959 }
8960 packet.init_techs_count = i;
8961 fc_assert(ARRAY_SIZE(packet.init_units) == ARRAY_SIZE(n->init_units));
8962 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
8963 const struct unit_type *t = n->init_units[i];
8964 if (t) {
8965 packet.init_units[i] = utype_number(t);
8966 } else {
8967 break;
8968 }
8969 }
8970 packet.init_units_count = i;
8972 == ARRAY_SIZE(n->init_buildings));
8973 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
8974 if (n->init_buildings[i] != B_LAST) {
8975 /* Impr_type_id to int */
8976 packet.init_buildings[i] = n->init_buildings[i];
8977 } else {
8978 break;
8979 }
8980 }
8981 packet.init_buildings_count = i;
8982
8983 lsend_packet_ruleset_nation(dest, &packet);
8985
8986 /* Send initial values of is_pickable */
8988}
8989
8990/**********************************************************************/
8994static void send_ruleset_styles(struct conn_list *dest)
8995{
8996 struct packet_ruleset_style packet;
8997
8998 styles_iterate(s) {
8999 packet.id = style_index(s);
9000 sz_strlcpy(packet.name, untranslated_name(&s->name));
9001 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
9002
9003 lsend_packet_ruleset_style(dest, &packet);
9005}
9006
9007/**********************************************************************/
9010static void send_ruleset_clauses(struct conn_list *dest)
9011{
9012 struct packet_ruleset_clause packet;
9013 int i;
9014
9015 for (i = 0; i < CLAUSE_COUNT; i++) {
9016 struct clause_info *info = clause_info_get(i);
9017
9018 packet.type = i;
9019 packet.enabled = info->enabled;
9020
9021 /* Shallow-copy (borrow) requirement vectors */
9022 packet.giver_reqs = info->giver_reqs;
9023 packet.receiver_reqs = info->receiver_reqs;
9024 packet.either_reqs = info->either_reqs;
9025
9026 lsend_packet_ruleset_clause(dest, &packet);
9027 }
9028}
9029
9030/**********************************************************************/
9034static void send_ruleset_multipliers(struct conn_list *dest)
9035{
9036 multipliers_iterate(pmul) {
9037 struct packet_ruleset_multiplier packet;
9038
9039 packet.id = multiplier_number(pmul);
9040 packet.start = pmul->start;
9041 packet.stop = pmul->stop;
9042 packet.step = pmul->step;
9043 packet.def = pmul->def;
9044 packet.offset = pmul->offset;
9045 packet.factor = pmul->factor;
9046 packet.minimum_turns = pmul->minimum_turns;
9047
9048 sz_strlcpy(packet.name, untranslated_name(&pmul->name));
9049 sz_strlcpy(packet.rule_name, rule_name_get(&pmul->name));
9050
9051 /* Shallow-copy (borrow) requirement vector */
9052 packet.reqs = pmul->reqs;
9053
9054 PACKET_STRVEC_INSERT(packet.helptext, pmul->helptext);
9055
9056 lsend_packet_ruleset_multiplier(dest, &packet);
9058}
9059
9060/**********************************************************************/
9064static void send_ruleset_cities(struct conn_list *dest)
9065{
9067 int k;
9068
9069 for (k = 0; k < game.control.num_city_styles; k++) {
9070 city_p.style_id = k;
9071
9072 /* Shallow-copy (borrow) requirement vector */
9073 city_p.reqs = city_styles[k].reqs;
9074
9077 sz_strlcpy(city_p.graphic, city_styles[k].graphic);
9078 sz_strlcpy(city_p.graphic_alt, city_styles[k].graphic_alt);
9079 sz_strlcpy(city_p.citizens_graphic, city_styles[k].citizens_graphic);
9080
9082 }
9083}
9084
9085/**********************************************************************/
9089static void send_ruleset_musics(struct conn_list *dest)
9090{
9091 struct packet_ruleset_music packet;
9092
9094 packet.id = pmus->id;
9095
9096 sz_strlcpy(packet.music_peaceful, pmus->music_peaceful);
9097 sz_strlcpy(packet.music_combat, pmus->music_combat);
9098
9099 /* Shallow-copy (borrow) requirement vector */
9100 packet.reqs = pmus->reqs;
9101
9102 lsend_packet_ruleset_music(dest, &packet);
9104}
9105
9106/**********************************************************************/
9110static void send_ruleset_game(struct conn_list *dest)
9111{
9113 int i;
9114
9116
9117 /* Per unit veteran system definition. */
9118 misc_p.veteran_levels = game.veteran->levels;
9119
9120 for (i = 0; i < misc_p.veteran_levels; i++) {
9121 const struct veteran_level *vlevel = game.veteran->definitions + i;
9122
9123 sz_strlcpy(misc_p.veteran_name[i], untranslated_name(&vlevel->name));
9124 misc_p.power_fact[i] = vlevel->power_fact;
9125 misc_p.move_bonus[i] = vlevel->move_bonus;
9126 misc_p.base_raise_chance[i] = vlevel->base_raise_chance;
9127 misc_p.work_raise_chance[i] = vlevel->work_raise_chance;
9128 }
9129
9130 fc_assert(sizeof(misc_p.global_init_techs)
9131 == sizeof(game.rgame.global_init_techs));
9132 fc_assert(ARRAY_SIZE(misc_p.global_init_techs)
9134 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9136 misc_p.global_init_techs[i] = game.rgame.global_init_techs[i];
9137 } else {
9138 break;
9139 }
9140 }
9141 misc_p.global_init_techs_count = i;
9142
9143 fc_assert(ARRAY_SIZE(misc_p.global_init_buildings)
9145 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9147 /* Impr_type_id to int */
9148 misc_p.global_init_buildings[i] =
9150 } else {
9151 break;
9152 }
9153 }
9154 misc_p.global_init_buildings_count = i;
9155
9156 misc_p.default_specialist = DEFAULT_SPECIALIST;
9157
9159
9160 misc_p.background_red = game.plr_bg_color->r;
9161 misc_p.background_green = game.plr_bg_color->g;
9162 misc_p.background_blue = game.plr_bg_color->b;
9163
9165}
9166
9167/**********************************************************************/
9171static void send_ruleset_team_names(struct conn_list *dest)
9172{
9174
9176 const char *name = team_slot_defined_name(tslot);
9177
9178 if (NULL == name) {
9179 /* End of defined names. */
9180 break;
9181 }
9182
9184 sz_strlcpy(team_name_info_p.team_name, name);
9185
9188}
9189
9190/**********************************************************************/
9193static void notify_ruleset_fallback(const char *msg)
9194{
9196}
9197
9198/**********************************************************************/
9201bool load_rulesets(const char *restore, const char *alt, bool compat_mode,
9202 rs_conversion_logger logger,
9203 bool act, bool buffer_script, bool load_luadata)
9204{
9205 set_ruleset_compat_mode(compat_mode);
9206
9207 if (load_rulesetdir(game.server.rulesetdir, compat_mode, logger,
9208 act, buffer_script, load_luadata)) {
9210 return TRUE;
9211 }
9212
9213 if (alt != NULL) {
9214 if (load_rulesetdir(alt, compat_mode, logger, act, buffer_script,
9215 load_luadata)) {
9217
9219 return TRUE;
9220 }
9221 }
9222
9223 /* Fallback to previous one. */
9224 if (restore != NULL) {
9225 if (load_rulesetdir(restore, compat_mode, logger, act, buffer_script, TRUE)) {
9227
9228 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Keeping previous one."));
9229
9231
9232 /* We're in sane state as restoring previous ruleset succeeded,
9233 * but return failure to indicate that this is not what caller
9234 * wanted. */
9235 return FALSE;
9236 }
9237 }
9238
9240
9241 /* Fallback to default one, but not if that's what we tried already */
9245 /* We're in sane state as fallback ruleset loading succeeded,
9246 * but return failure to indicate that this is not what caller
9247 * wanted. */
9249
9250 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Switching to default one."));
9251
9252 return FALSE;
9253 }
9254 }
9255
9256#ifdef FREECIV_WEB
9257 log_normal(_("Cannot load any ruleset. Freeciv-web ruleset is available from "
9258 "https://github.com/freeciv/freeciv-web"));
9259#endif /* FREECIV_WEB */
9260
9261 /* Cannot load even default ruleset, we're in completely unusable state */
9263
9265}
9266
9267/**********************************************************************/
9271{
9272 if (file != NULL) {
9273 secfile_destroy(file);
9274 }
9275}
9276
9277/**********************************************************************/
9286
9287/**********************************************************************/
9291static bool load_rulesetdir(const char *rsdir, bool compat_mode,
9292 rs_conversion_logger logger,
9293 bool act, bool buffer_script, bool load_luadata)
9294{
9297 struct section_file *actionfile;
9298 bool ok = TRUE;
9300
9301 log_normal(_("Loading rulesets."));
9302
9304 compat_info.compat_mode = compat_mode;
9305 compat_info.log_cb = logger;
9306
9308 /* Reset the list of available player colors. */
9312
9313 if (script_buffer != NULL) {
9316 }
9317 if (parser_buffer != NULL) {
9320 }
9321
9322 server.playable_nations = 0;
9323
9327 buildfile = openload_ruleset_file("buildings", rsdir);
9328 govfile = openload_ruleset_file("governments", rsdir);
9330 terrfile = openload_ruleset_file("terrain", rsdir);
9335
9336 if (load_luadata) {
9338 } else {
9340 }
9341
9342 if (techfile == NULL
9343 || buildfile == NULL
9344 || govfile == NULL
9345 || unitfile == NULL
9346 || terrfile == NULL
9347 || stylefile == NULL
9348 || cityfile == NULL
9349 || nationfile == NULL
9350 || effectfile == NULL
9351 || actionfile == NULL
9352 || gamefile == NULL) {
9353 ok = FALSE;
9354 }
9355
9356 if (ok) {
9357 /* Note: Keep load_game_names() first so that compat_info.version is
9358 * correctly initialized. */
9368 }
9369
9370 if (ok) {
9372 }
9373
9374 if (ok) {
9376 }
9377 if (ok) {
9379 }
9380 if (ok) {
9382 }
9383 if (ok) {
9385 }
9386 if (ok) {
9387 /* Terrain must precede nations and units */
9389 }
9390 if (ok) {
9392 }
9393 if (ok) {
9395 }
9396 if (ok) {
9398 }
9399 if (ok) {
9401 }
9402 if (ok) {
9404 }
9405 if (ok) {
9407 }
9408
9409 if (ok) {
9410 /* Init nations we just loaded. */
9412
9413 /* Needed by role_unit_precalcs(). */
9415
9416 /* Prepare caches we want to sanity check. */
9420
9423 }
9424
9425 if (ok) {
9426 /* Only load settings for a sane ruleset */
9427 ok = settings_ruleset(gamefile, "settings", act,
9428 compat_info.compat_mode
9429 && compat_info.version < RSFORMAT_CURRENT);
9430
9431 if (ok) {
9433 }
9434 }
9435
9447
9448 if (extra_sections) {
9451 }
9452 if (base_sections) {
9455 }
9456 if (road_sections) {
9459 }
9460 if (resource_sections) {
9463 }
9464 if (terrain_sections) {
9467 }
9468
9469 if (ok) {
9471 }
9472
9473 if (ok) {
9474 char **buffer = buffer_script ? &script_buffer : NULL;
9475
9477
9479
9480 ok = (openload_script_file("script", rsdir, buffer, FALSE) == TRI_YES);
9481 }
9482
9483 if (ok) {
9484 enum fc_tristate pret;
9485 char **buffer = buffer_script ? &parser_buffer : NULL;
9486
9487 pret = openload_script_file("parser", rsdir, buffer, compat_info.compat_mode);
9488
9489 if (pret == TRI_MAYBE && buffer_script) {
9491 "-- This file is for lua-functionality for parsing luadata.txt\n-- of this ruleset.");
9492 }
9493
9494 ok = (pret != TRI_NO);
9495 }
9496
9497 if (ok && !buffer_script) {
9498 ok = (openload_script_file("default", rsdir, NULL, FALSE) == TRI_YES);
9499 }
9500
9501 if (ok && act) {
9502 /* Populate remaining caches. */
9509 ptype->unknown_move_cost = utype_unknown_move_cost(ptype);
9513
9514 /* Build advisors unit class cache corresponding to loaded rulesets */
9516 CALL_FUNC_EACH_AI(units_ruleset_init);
9517
9518 /* We may need to adjust the number of AI players
9519 * if the number of available nations changed. */
9521 }
9522
9523 return ok;
9524}
9525
9526/**********************************************************************/
9530{
9531 struct section_file *file;
9532 bool ok = TRUE;
9533
9535 if (file == NULL) {
9537 "Could not load game.ruleset:\n%s",
9538 secfile_error());
9539 ok = FALSE;
9540 }
9541 if (ok) {
9542 settings_ruleset(file, "settings", TRUE, FALSE);
9543 secfile_destroy(file);
9544 }
9545
9546 return ok;
9547}
9548
9549/**********************************************************************/
9552void send_rulesets(struct conn_list *dest)
9553{
9555
9556 /* ruleset_control also indicates to client that ruleset sending starts. */
9558
9559 /* Currently containing control-kind of data of nation sets and groups,
9560 * this too must be sent before any requirement vector may depend on
9561 * that data. */
9563
9564 send_ruleset_game(dest);
9574 send_ruleset_techs(dest);
9577 send_ruleset_units(dest);
9579 send_ruleset_extras(dest);
9580 send_ruleset_bases(dest);
9581 send_ruleset_roads(dest);
9584 send_ruleset_goods(dest);
9586 send_ruleset_styles(dest);
9588 send_ruleset_cities(dest);
9590 send_ruleset_musics(dest);
9591 send_ruleset_cache(dest);
9592
9593 /* Indicate client that all rulesets have now been sent. */
9595
9596 /* changed game settings will be send in
9597 * connecthand.c:establish_new_connection() */
9598
9600}
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:5707
void actions_rs_pre_san_gen(void)
Definition actions.c:889
const char * action_min_range_ruleset_var_name(int act)
Definition actions.c:6454
const char * action_blocked_by_ruleset_var_name(const struct action *act)
Definition actions.c:7164
bool action_is_in_use(struct action *paction)
Definition actions.c:5661
const char * action_post_success_forced_ruleset_var_name(const struct action *act)
Definition actions.c:7358
struct action * action_by_rule_name(const char *name)
Definition actions.c:1079
const char * action_rule_name(const struct action *action)
Definition actions.c:1216
const char * action_actor_consuming_always_ruleset_var_name(action_id act)
Definition actions.c:6991
const char * action_max_range_ruleset_var_name(int act)
Definition actions.c:6632
const char * action_target_kind_ruleset_var_name(int act)
Definition actions.c:6819
void action_enabler_add(struct action_enabler *enabler)
Definition actions.c:1526
const char * action_ui_name_default(int act)
Definition actions.c:6090
struct action_enabler * action_enabler_new(void)
Definition actions.c:1475
bool action_enabler_possible_actor(const struct action_enabler *ae)
Definition actions.c:5596
bool action_id_is_internal(action_id act)
Definition actions.c:5699
struct action_enabler_list * action_enablers_for_action(action_id action)
Definition actions.c:1559
const char * action_ui_name_ruleset_var_name(int act)
Definition actions.c:5792
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:245
#define action_auto_perf_iterate_end
Definition actions.h:350
#define action_enablers_iterate_end
Definition actions.h:283
#define ACTION_AUTO_MOVED_ADJ
Definition actions.h:375
#define ACTION_AUTO_POST_BRIBE_UNIT
Definition actions.h:376
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:421
#define ACTION_AUTO_UPKEEP_GOLD
Definition actions.h:373
#define enabler_get_action_id(_enabler_)
Definition actions.h:187
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define NUM_ACTIONS
Definition actions.h:63
#define ACTION_AUTO_ESCAPE_STACK
Definition actions.h:382
#define action_has_result(_act_, _res_)
Definition actions.h:184
#define ACTION_AUTO_ESCAPE_CITY
Definition actions.h:381
#define action_enabler_list_iterate_end
Definition actions.h:194
#define ACTION_DISTANCE_UNLIMITED
Definition actions.h:105
#define action_by_result_iterate_end
Definition actions.h:249
#define ACTION_AUTO_POST_WIPE_UNITS
Definition actions.h:383
#define ACTION_AUTO_UPKEEP_SHIELD
Definition actions.h:374
#define action_iterate_end
Definition actions.h:218
#define ACTION_AUTO_POST_BRIBE_STACK
Definition actions.h:377
#define action_enablers_iterate(_enabler_)
Definition actions.h:277
#define ACTION_AUTO_POST_ATTACK2
Definition actions.h:379
#define action_enabler_list_iterate(action_enabler_list, aenabler)
Definition actions.h:192
#define action_id(_act_)
Definition actions.h:426
#define action_iterate(_act_)
Definition actions.h:214
#define action_auto_perf_iterate(_act_perf_)
Definition actions.h:338
#define ACTION_AUTO_UPKEEP_FOOD
Definition actions.h:372
#define ACTION_AUTO_POST_ATTACK
Definition actions.h:378
#define ACTION_AUTO_POST_COLLECT_RANSOM
Definition actions.h:380
#define ACTION_NONE
Definition actions.h:59
int actres_min_range_default(enum action_result result)
Definition actres.c:376
int actres_max_range_default(enum action_result result)
Definition actres.c:466
enum action_target_kind actres_target_kind_default(enum action_result result)
Definition actres.c:770
void adv_units_ruleset_init(void)
Definition advruleset.c:33
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define str
Definition astring.c:76
#define n
Definition astring.c:77
Base_type_id base_number(const struct base_type *pbase)
Definition base.c:96
void base_type_init(struct extra_type *pextra, int idx)
Definition base.c:121
bool territory_claiming_base(const struct base_type *pbase)
Definition base.c:162
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
void city_styles_alloc(int num)
Definition city.c:3421
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:842
#define output_type_iterate_end
Definition city.h:848
static struct fc_sockaddr_list * list
Definition clinet.c:102
char * incite_cost
Definition comments.c:76
#define MAX_LEN_CONTENT
Definition conn_types.h:32
#define MAX_LEN_MSG
Definition conn_types.h:37
void conn_list_compression_thaw(const struct conn_list *pconn_list)
Definition connection.c: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
struct clause_info * clause_info_get(enum clause_type type)
Definition diptreaty.c:292
const char * disaster_rule_name(struct disaster_type *pdis)
Definition disaster.c:105
Disaster_type_id disaster_number(const struct disaster_type *pdis)
Definition disaster.c:56
Disaster_type_id disaster_index(const struct disaster_type *pdis)
Definition disaster.c:69
#define disaster_type_iterate(_p)
Definition disaster.h:82
#define disaster_type_iterate_end
Definition disaster.h:88
int int id
Definition editgui_g.h:28
struct @22::@23 reqs
void send_ruleset_cache(struct conn_list *dest)
Definition effects.c:609
struct effect * effect_new(enum effect_type type, int value, struct multiplier *pmul)
Definition effects.c:186
void user_effect_ai_valued_set(enum effect_type tgt, enum effect_type valued_as)
Definition effects.c:1346
struct effect_list * get_effects(enum effect_type effect_type)
Definition effects.c:143
enum effect_type user_effect_ai_valued_as(enum effect_type real)
Definition effects.c:1357
void effect_req_append(struct effect *peffect, struct requirement req)
Definition effects.c:266
bool is_user_effect(enum effect_type eff)
Definition effects.c:1337
#define effect_list_iterate_end
Definition effects.h:81
#define effect_list_iterate(effect_list, peffect)
Definition effects.h:79
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
const char * extra_flag_helptxt(enum extra_flag_id id)
Definition extras.c:988
void set_user_extra_flag_name(enum extra_flag_id id, const char *name, const char *helptxt)
Definition extras.c:947
bool is_extra_caused_by_worker_action(const struct extra_type *pextra)
Definition extras.c:1046
struct extra_type_list * extra_type_list_of_zoccers(void)
Definition extras.c:267
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:875
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:249
void extra_to_caused_by_list(struct extra_type *pextra, enum extra_cause cause)
Definition extras.c:312
struct extra_type * extra_by_number(int id)
Definition extras.c:183
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:510
#define MAX_DISASTER_TYPES
Definition fc_types.h:52
#define MAX_VET_LEVELS
Definition fc_types.h:49
@ ROCO_RAILROAD
Definition fc_types.h:961
@ ROCO_NONE
Definition fc_types.h:961
@ ROCO_RIVER
Definition fc_types.h:961
@ ROCO_ROAD
Definition fc_types.h:961
#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_GOODS_TYPES
Definition fc_types.h:51
#define EC_NATURAL_DEFENSIVE
Definition fc_types.h:824
#define EC_SPECIAL
Definition fc_types.h:822
int action_id
Definition fc_types.h:248
#define SP_MAX
Definition fc_types.h:267
#define EC_NONE
Definition fc_types.h:821
#define EC_NOT_AGGRESSIVE
Definition fc_types.h:825
#define EC_DEFENSIVE
Definition fc_types.h:823
#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:274
#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:61
void game_ruleset_init(void)
Definition game.c:517
void game_ruleset_free(void)
Definition game.c:566
struct world wld
Definition game.c:62
#define RS_DEFAULT_RANSOM_GOLD
Definition game.h:874
#define RS_DEFAULT_GRANARY_FOOD_INI
Definition game.h:826
#define RS_DEFAULT_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:866
#define RS_MIN_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:807
#define RS_MAX_TECH_UPKEEP_DIVIDER
Definition game.h:886
#define RS_MIN_ILLNESS_POLLUTION_PCT
Definition game.h:793
#define RS_DEFAULT_NUKE_POP_LOSS_PCT
Definition game.h:863
#define RS_MAX_BORDER_RADIUS_SQ_CITY
Definition game.h:800
#define RS_DEFAULT_BASE_POLLUTION
Definition game.h:849
#define RS_MIN_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:789
#define RS_MAX_ILLNESS_BASE_FACTOR
Definition game.h:782
#define RS_DEFAULT_INCITE_TOTAL_FCT
Definition game.h:822
#define RS_DEFAULT_ILLNESS_BASE_FACTOR
Definition game.h:780
#define RS_DEFAULT_NEG_YEAR_LABEL
Definition game.h:776
#define RS_MIN_NUKE_POP_LOSS_PCT
Definition game.h:864
#define RS_MIN_INCITE_IMPROVEMENT_FCT
Definition game.h:815
#define RS_MIN_FOOD_COST
Definition game.h:859
#define RS_MIN_BASE_BRIBE_COST
Definition game.h:871
#define RS_MAX_NUKE_POP_LOSS_PCT
Definition game.h:865
#define RS_DEFAULT_INCITE_IMPROVEMENT_FCT
Definition game.h:814
#define RS_MAX_INCITE_IMPROVEMENT_FCT
Definition game.h:816
#define RS_MIN_RANSOM_GOLD
Definition game.h:875
#define RS_ACTION_NO_MAX_DISTANCE
Definition game.h:898
#define RS_DEFAULT_BASE_BRIBE_COST
Definition game.h:870
#define RS_MAX_INCITE_BASE_COST
Definition game.h:812
#define RS_DEFAULT_TECH_UPKEEP_DIVIDER
Definition game.h:884
#define RS_DEFAULT_HAPPY_COST
Definition game.h:854
#define RS_MIN_UPGRADE_VETERAN_LOSS
Definition game.h:881
#define RS_MIN_ILLNESS_MIN_SIZE
Definition game.h:785
#define RS_DEFAULT_POISON_EMPTIES_FOOD_STOCK
Definition game.h:888
#define RS_DEFAULT_GRANARY_FOOD_INC
Definition game.h:828
#define RS_DEFAULT_ILLNESS_ON
Definition game.h:778
#define RS_MAX_FOOD_COST
Definition game.h:860
#define RS_MAX_HAPPY_COST
Definition game.h:856
#define GAME_DEFAULT_CELEBRATESIZE
Definition game.h:507
#define RS_MIN_ILLNESS_BASE_FACTOR
Definition game.h:781
#define RS_DEFAULT_STEAL_MAP_REVEALS_CITIES
Definition game.h:889
#define RS_MIN_TECH_UPKEEP_DIVIDER
Definition game.h:885
#define RS_MAX_RANSOM_GOLD
Definition game.h:876
#define RS_MIN_HAPPY_COST
Definition game.h:855
#define RS_MIN_BORDER_RADIUS_SQ_CITY
Definition game.h:799
#define GAME_DEFAULT_RULESETDIR
Definition game.h:681
#define RS_MIN_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:867
#define RS_MAX_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:808
#define RS_DEFAULT_UPGRADE_VETERAN_LOSS
Definition game.h:880
#define RS_MAX_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:868
#define RS_MAX_INCITE_UNIT_FCT
Definition game.h:820
#define RS_MIN_VIS_RADIUS_SQ
Definition game.h:846
#define RS_DEFAULT_CALENDAR_SKIP_0
Definition game.h:796
#define RS_MAX_ILLNESS_MIN_SIZE
Definition game.h:786
#define RS_DEFAULT_CITY_RADIUS_SQ
Definition game.h:841
#define GAME_DEFAULT_START_YEAR
Definition game.h:748
#define RS_MAX_BORDER_SIZE_EFFECT
Definition game.h:804
#define RS_DEFAULT_BORDER_SIZE_EFFECT
Definition game.h:802
#define RS_MAX_BASE_BRIBE_COST
Definition game.h:872
#define RS_MIN_INCITE_BASE_COST
Definition game.h:811
#define RS_DEFAULT_PILLAGE_SELECT
Definition game.h:878
#define RS_MIN_CITY_RADIUS_SQ
Definition game.h:842
#define RS_MIN_CITY_CENTER_OUTPUT
Definition game.h:833
#define RS_MAX_GRANARY_FOOD_INC
Definition game.h:830
#define RS_MAX_CITY_CENTER_OUTPUT
Definition game.h:834
#define RS_MAX_CITY_RADIUS_SQ
Definition game.h:843
#define RS_DEFAULT_POS_YEAR_LABEL
Definition game.h:774
#define RS_MIN_INCITE_UNIT_FCT
Definition game.h:819
#define RS_MIN_BORDER_SIZE_EFFECT
Definition game.h:803
#define RS_DEFAULT_VIS_RADIUS_SQ
Definition game.h:845
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:806
#define RS_DEFAULT_TIRED_ATTACK
Definition game.h:862
#define RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS
Definition game.h:890
#define RS_MAX_ILLNESS_POLLUTION_PCT
Definition game.h:794
#define RS_DEFAULT_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:788
#define RS_DEFAULT_FOOD_COST
Definition game.h:858
#define RS_DEFAULT_INCITE_UNIT_FCT
Definition game.h:818
#define RS_MAX_INCITE_TOTAL_FCT
Definition game.h:824
#define RS_DEFAULT_INCITE_BASE_COST
Definition game.h:810
#define GAME_DEFAULT_ANGRYCITIZEN
Definition game.h:398
#define RS_DEFAULT_CITY_CENTER_OUTPUT
Definition game.h:832
#define RS_MIN_INCITE_TOTAL_FCT
Definition game.h:823
#define RS_DEFAULT_ILLNESS_POLLUTION_PCT
Definition game.h:792
#define RS_MAX_UPGRADE_VETERAN_LOSS
Definition game.h:882
static void set_ruleset_compat_mode(bool active)
Definition game.h:362
#define RS_MAX_VIS_RADIUS_SQ
Definition game.h:847
#define RS_MIN_GRANARY_FOOD_INC
Definition game.h:829
#define RS_MAX_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:790
#define RS_DEFAULT_ILLNESS_MIN_SIZE
Definition game.h:784
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY
Definition game.h:798
const struct nation_type * ruler_title_nation(const struct ruler_title *pruler_title)
Definition government.c:365
struct ruler_title * government_ruler_title_new(struct government *pgovern, const struct nation_type *pnation, const char *ruler_male_title, const char *ruler_female_title)
Definition government.c:325
const char * ruler_title_female_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:383
Government_type_id government_count(void)
Definition government.c:71
const char * ruler_title_male_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:374
void governments_alloc(int num)
Definition government.c:529
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
const struct ruler_title_hash * government_ruler_titles(const struct government *pgovern)
Definition government.c:314
Government_type_id government_index(const struct government *pgovern)
Definition government.c:82
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
#define governments_iterate(NAME_pgov)
Definition government.h:124
#define G_LAST
Definition government.h:48
#define ruler_titles_iterate(ARG_hash, NAME_rule_title)
Definition government.h:38
#define ruler_titles_iterate_end
Definition government.h:41
#define governments_iterate_end
Definition government.h:127
const char * title
Definition repodlgs.c:1314
GType type
Definition repodlgs.c:1313
struct impr_type * improvement_by_number(const Impr_type_id id)
Impr_type_id improvement_number(const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
void improvement_feature_cache_init(void)
Definition improvement.c:92
struct impr_type * improvement_by_rule_name(const char *name)
void set_user_impr_flag_name(enum impr_flag_id id, const char *name, const char *helptxt)
const char * impr_flag_helptxt(enum impr_flag_id id)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define B_LAST
Definition improvement.h:42
const char * name
Definition inputfile.c:127
void vdo_log(const char *file, const char *function, int line, bool print_from_where, enum log_level level, char *buf, int buflen, const char *message, va_list args)
Definition log.c:403
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define MAX_LEN_LOG_LINE
Definition log.h:27
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_do_output_for_level(level)
Definition log.h:90
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
log_level
Definition log.h:29
@ LOG_ERROR
Definition log.h:31
@ LOG_FATAL
Definition log.h:30
#define log_error(message,...)
Definition log.h:104
struct terrain_misc terrain_control
Definition map.c:68
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
int utype_unknown_move_cost(const struct unit_type *utype)
Definition movement.c:104
void init_move_fragments(void)
Definition movement.c:960
#define SINGLE_MOVE
Definition movement.h:26
const char * multiplier_rule_name(const struct multiplier *pmul)
Multiplier_type_id multiplier_number(const struct multiplier *pmul)
Definition multipliers.c:67
struct multiplier * multiplier_by_rule_name(const char *name)
Multiplier_type_id multiplier_index(const struct multiplier *pmul)
Definition multipliers.c:80
#define multipliers_iterate(_mul_)
Definition multipliers.h:61
#define multipliers_iterate_end
Definition multipliers.h:67
static void name_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name)
static const char * rule_name_get(const struct name_translation *ptrans)
static const char * untranslated_name(const struct name_translation *ptrans)
static void names_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name, const char *rule_name)
void nation_group_set_match(struct nation_group *pgroup, int match)
Definition nation.c: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_INSERT(dest, src)
Definition packets.h:188
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:2647
void playercolor_free(void)
Definition plrhand.c:3348
void playercolor_init(void)
Definition plrhand.c:3338
int playercolor_count(void)
Definition plrhand.c:3387
void playercolor_add(struct rgbcolor *prgbcolor)
Definition plrhand.c:3367
void count_playable_nations(void)
Definition plrhand.c:2604
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:51
const char * secfile_error(void)
const char * section_name(const struct section *psection)
void secfile_destroy(struct section_file *secfile)
bool entry_bool_get(const struct entry *pentry, bool *value)
void secfile_check_unused(const struct section_file *secfile)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
struct section_list * secfile_sections_by_name_prefix(const struct section_file *secfile, const char *prefix)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
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,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
bool entry_int_get(const struct entry *pentry, int *value)
const char * secfile_name(const struct section_file *secfile)
struct entry * secfile_entry_by_path(const struct section_file *secfile, const char *path)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
int secfile_lookup_int_def_min_max(const struct section_file *secfile, int defval, int minval, int maxval, const char *path,...)
enum entry_type entry_type_get(const struct entry *pentry)
@ ENTRY_FILEREFERENCE
@ ENTRY_LONG_COMMENT
@ ENTRY_INT
@ ENTRY_FLOAT
@ ENTRY_STR
@ ENTRY_ILLEGAL
@ ENTRY_BOOL
#define secfile_lookup_enum_vec(secfile, dim, specenum_type, path,...)
#define secfile_lookup_enum_default(secfile, defval, specenum_type, path,...)
#define section_list_iterate(seclist, psection)
#define section_list_iterate_end
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
void req_vec_problem_free(struct req_vec_problem *issue)
struct req_vec_problem * req_vec_get_first_missing_univ(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
struct req_vec_problem * req_vec_get_first_redundant_req(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor, char *path,...)
Definition rgbcolor.c:90
Road_type_id road_number(const struct road_type *proad)
Definition road.c:32
void road_integrators_cache_init(void)
Definition road.c:111
void road_type_init(struct extra_type *pextra, int idx)
Definition road.c:93
bool load_action_ui_name_3_3(struct section_file *file, int act, const char *entry_name, struct rscompat_info *compat)
Definition rscompat.c:762
void rscompat_civil_war_effects_3_3(struct section_file *game_rs)
Definition rscompat.c:730
const char * rscompat_effect_name_3_3(const char *old_name)
Definition rscompat.c:671
bool rscompat_names(struct rscompat_info *info)
Definition rscompat.c:345
void rscompat_postprocess(struct rscompat_info *info)
Definition rscompat.c:469
const char * rscompat_utype_flag_name_3_3(const char *old_name)
Definition rscompat.c:647
int rscompat_check_capabilities(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:70
void rscompat_enablers_add_obligatory_hard_reqs(void)
Definition rscompat.c:290
const char * blocked_by_old_name_3_3(const char *new_name)
Definition rscompat.c:685
const char * rscompat_universal_name_3_3(const char *old_name)
Definition rscompat.c:659
void rscompat_init_info(struct rscompat_info *info)
Definition rscompat.c:61
bool rscompat_check_cap_and_version(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:135
bool sanity_check_ruleset_data(struct rscompat_info *compat)
Definition rssanity.c:903
bool autoadjust_ruleset_data(void)
Definition rssanity.c:1616
#define ENABLER_SECTION_PREFIX
Definition ruleload.c:111
#define check_cityname(name)
Definition ruleload.c:118
static int ruleset_purge_redundant_reqs_enablers(void)
Definition ruleload.c:425
static void ruleset_load_traits(struct trait_limits *out, struct section_file *file, const char *secname, const char *field_prefix)
Definition ruleload.c:1270
static bool load_rulesetdir(const char *rsdir, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleload.c:9291
#define STYLE_SECTION_PREFIX
Definition ruleload.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 ruleload.c:1171
static bool load_ruleset_veteran(struct section_file *file, const char *path, struct veteran_system **vsystem, char *err, size_t err_len)
Definition ruleload.c:1946
static bool load_terrain_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2739
static bool load_style_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5595
int ruleset_purge_unused_entities(void)
Definition ruleload.c:315
#define MUSICSTYLE_SECTION_PREFIX
Definition ruleload.c:91
static char * road_sections
Definition ruleload.c:129
static bool load_ruleset_governments(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4300
#define MULTIPLIER_SECTION_PREFIX
Definition ruleload.c:114
static struct requirement_vector reqs_list
Definition ruleload.c:131
static void send_ruleset_techs(struct conn_list *dest)
Definition ruleload.c:8201
#define section_strlcpy(dst, src)
Definition ruleload.c:123
static bool load_action_range(struct section_file *file, action_id act)
Definition ruleload.c:6303
#define check_name(name)
Definition ruleload.c:117
static void send_ruleset_units(struct conn_list *dest)
Definition ruleload.c:8022
static void send_ruleset_governments(struct conn_list *dest)
Definition ruleload.c:8842
static bool load_action_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1439
static struct extra_type * lookup_resource(const char *filename, const char *name, const char *jsection)
Definition ruleload.c:1150
static struct section_file * openload_luadata_file(const char *rsdir)
Definition ruleload.c:628
static bool load_ruleset_techs(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1577
static bool purge_unused_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:329
void rulesets_deinit(void)
Definition ruleload.c:9281
static void send_ruleset_resources(struct conn_list *dest)
Definition ruleload.c:8485
static bool load_ruleset_buildings(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2615
static char * terrain_sections
Definition ruleload.c:126
static bool lookup_building_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleload.c:1002
static void nullcheck_secfile_destroy(struct section_file *file)
Definition ruleload.c:9270
static void send_ruleset_clauses(struct conn_list *dest)
Definition ruleload.c:9010
static void send_ruleset_game(struct conn_list *dest)
Definition ruleload.c:9110
char * parser_buffer
Definition ruleload.c:211
#define NATION_SECTION_PREFIX
Definition ruleload.c:97
static bool load_ruleset_effects(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:6046
static bool lookup_cbonus_list(struct combat_bonus_list *list, struct section_file *file, const char *sec, const char *sub)
Definition ruleload.c:787
static void send_ruleset_nations(struct conn_list *dest)
Definition ruleload.c:8884
static void send_ruleset_roads(struct conn_list *dest)
Definition ruleload.c:8628
static int ruleset_purge_unused_enablers(void)
Definition ruleload.c:246
#define UEFF_SECTION_PREFIX
Definition ruleload.c:92
static bool is_on_allowed_list(const char *name, const char **list, size_t len)
Definition ruleload.c:4692
static void send_ruleset_tech_classes(struct conn_list *dest)
Definition ruleload.c:8183
static void send_ruleset_action_enablers(struct conn_list *dest)
Definition ruleload.c:8769
static void send_ruleset_control(struct conn_list *dest)
Definition ruleload.c:4498
bool load_rulesets(const char *restore, const char *alt, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleload.c:9201
#define GOODS_SECTION_PREFIX
Definition ruleload.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 ruleload.c:217
#define TERRAIN_SECTION_PREFIX
Definition ruleload.c:106
static struct section_file * openload_ruleset_file(const char *whichset, const char *rsdir)
Definition ruleload.c:573
static void send_ruleset_musics(struct conn_list *dest)
Definition ruleload.c:9089
int ruleset_purge_redundant_reqs(void)
Definition ruleload.c:492
static int secfile_lookup_int_default_min_max(struct section_file *file, int def, int min, int max, const char *path,...) fc__attribute((__format__(__printf__
Definition ruleload.c:6224
static char * base_sections
Definition ruleload.c:128
#define DISASTER_SECTION_PREFIX
Definition ruleload.c:109
static void send_ruleset_goods(struct conn_list *dest)
Definition ruleload.c:8664
static const char name_too_long[]
Definition ruleload.c:121
bool reload_rulesets_settings(void)
Definition ruleload.c:9529
static struct strvec * lookup_strvec(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleload.c:1130
#define CITYSTYLE_SECTION_PREFIX
Definition ruleload.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 ruleload.c:846
static bool load_game_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1309
static void send_ruleset_counters(struct conn_list *dest)
Definition ruleload.c:8297
static void send_ruleset_specialists(struct conn_list *dest)
Definition ruleload.c:8158
#define ADVANCE_SECTION_PREFIX
Definition ruleload.c:87
#define EFFECT_SECTION_PREFIX
Definition ruleload.c:93
static void send_ruleset_action_auto_performers(struct conn_list *dest)
Definition ruleload.c:8788
static bool load_government_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4218
static bool load_action_blocked_by_list(struct section_file *file, const char *filename, struct action *paction, struct rscompat_info *compat)
Definition ruleload.c:6368
static void send_ruleset_team_names(struct conn_list *dest)
Definition ruleload.c:9171
static void send_ruleset_cities(struct conn_list *dest)
Definition ruleload.c:9064
static bool purge_redundant_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:414
static char * lookup_string(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleload.c:1110
static const char * check_leader_names(struct nation_type *pnation)
Definition ruleload.c:4536
#define ACTION_ENABLER_SECTION_PREFIX
Definition ruleload.c:112
#define BASE_SECTION_PREFIX
Definition ruleload.c:101
static int ruleset_purge_redundant_reqs_effects(void)
Definition ruleload.c:463
static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir, char **buffer, bool optional)
Definition ruleload.c:601
char * get_parser_buffer(void)
Definition ruleload.c:564
#define ACTION_SECTION_PREFIX
Definition ruleload.c:113
static bool load_building_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2534
#define EXTRA_SECTION_PREFIX
Definition ruleload.c:100
void send_rulesets(struct conn_list *dest)
Definition ruleload.c:9552
#define CLAUSE_SECTION_PREFIX
Definition ruleload.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 ruleload.c:878
static char * resource_sections
Definition ruleload.c:125
#define UNIT_SECTION_PREFIX
Definition ruleload.c:108
#define ACHIEVEMENT_SECTION_PREFIX
Definition ruleload.c:110
static bool load_ruleset_cities(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5835
static bool load_ruleset_styles(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5656
static struct government * lookup_government(struct section_file *file, const char *entry, const char *filename, struct government *fallback)
Definition ruleload.c:1085
static bool load_ruleset_units(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2067
char * script_buffer
Definition ruleload.c:210
static bool lookup_time(const struct section_file *secfile, int *turns, const char *sec_name, const char *property_name, const char *filename, const char *item_name, bool *ok)
Definition ruleload.c:1221
static void send_ruleset_styles(struct conn_list *dest)
Definition ruleload.c:8994
#define NATION_GROUP_SECTION_PREFIX
Definition ruleload.c:96
static char * extra_sections
Definition ruleload.c:127
#define RULES_SUFFIX
Definition ruleload.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 ruleload.c:656
static void send_ruleset_disasters(struct conn_list *dest)
Definition ruleload.c:8693
static bool purge_duplicate_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:369
static bool lookup_tech_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleload.c:938
#define MAX_SECTION_LABEL
Definition ruleload.c:122
#define BUILDING_SECTION_PREFIX
Definition ruleload.c:89
static bool load_ruleset_game(struct section_file *file, bool act, struct rscompat_info *compat)
Definition ruleload.c:6510
static bool load_nation_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4556
static void send_ruleset_achievements(struct conn_list *dest)
Definition ruleload.c:8718
#define SCRIPT_SUFFIX
Definition ruleload.c:85
static void send_ruleset_bases(struct conn_list *dest)
Definition ruleload.c:8606
static bool load_ruleset_terrain(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:3071
static int ruleset_purge_unused_effects(void)
Definition ruleload.c:292
static bool load_action_actor_consuming_always(struct section_file *file, action_id act)
Definition ruleload.c:6351
static bool load_action_post_success_force(struct section_file *file, const char *filename, int performer_slot, struct action *paction)
Definition ruleload.c:6439
static bool load_tech_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1459
#define SPECIALIST_SECTION_PREFIX
Definition ruleload.c:105
#define COUNTER_SECTION_PREFIX
Definition ruleload.c:115
static bool load_action_kind(struct section_file *file, action_id act)
Definition ruleload.c:6328
static void send_ruleset_multipliers(struct conn_list *dest)
Definition ruleload.c:9034
char * get_script_buffer(void)
Definition ruleload.c:556
static void send_ruleset_actions(struct conn_list *dest)
Definition ruleload.c:8739
static bool load_city_name_list(struct section_file *file, struct nation_type *pnation, const char *secfile_str1, const char *secfile_str2, const char **allowed_terrains, size_t atcount)
Definition ruleload.c:4708
static bool load_action_auto_uflag_block(struct section_file *file, struct action_auto_perf *auto_perf, const char *uflags_path, const char *filename)
Definition ruleload.c:5734
static bool load_ruleset_nations(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4878
static bool load_action_auto_actions(struct section_file *file, struct action_auto_perf *auto_perf, const char *actions_path, const char *filename)
Definition ruleload.c:5777
static void send_ruleset_unit_classes(struct conn_list *dest)
Definition ruleload.c:7974
#define TECH_CLASS_SECTION_PREFIX
Definition ruleload.c:88
#define RESOURCE_SECTION_PREFIX
Definition ruleload.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 ruleload.c:1054
static void send_ruleset_extras(struct conn_list *dest)
Definition ruleload.c:8504
#define rs_sanity_veteran(_path, _entry, _i, _condition, _action)
static void send_ruleset_terrain(struct conn_list *dest)
Definition ruleload.c:8378
#define GOVERNMENT_SECTION_PREFIX
Definition ruleload.c:94
static bool load_unit_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1788
static void send_ruleset_trade_routes(struct conn_list *dest)
Definition ruleload.c:8821
static bool load_ruleset_actions(struct section_file *file, struct section_file *gamefile, struct rscompat_info *compat)
Definition ruleload.c:7575
static void notify_ruleset_fallback(const char *msg)
Definition ruleload.c:9193
static bool lookup_bv_actions(struct section_file *file, const char *filename, bv_actions *target, const char *path)
Definition ruleload.c:6476
static void send_ruleset_buildings(struct conn_list *dest)
Definition ruleload.c:8318
#define UNIT_CLASS_SECTION_PREFIX
Definition ruleload.c:107
static bool ruleset_load_names(struct name_translation *pname, const char *domain, struct section_file *file, const char *sec_name)
Definition ruleload.c:1247
#define ROAD_SECTION_PREFIX
Definition ruleload.c:102
static const char * valid_ruleset_filename(const char *subdir, const char *name, const char *extension, bool optional)
Definition ruleload.c:511
static bool load_action_range_max(struct section_file *file, action_id act)
Definition ruleload.c:6262
static bool load_muuk_as_action_auto(struct section_file *file, struct action_auto_perf *auto_perf, const char *item, const char *filename)
Definition ruleload.c:5813
#define NATION_SET_SECTION_PREFIX
Definition ruleload.c:95
#define RS_DEFAULT_CONVERT_SPEED
Definition ruleload.h:123
#define RS_DEFAULT_DAMAGE_REDUCES_BOMBARD_RATE
Definition ruleload.h:109
#define RS_DEFAULT_WORLD_PEACE_TURNS
Definition ruleload.h:99
#define RS_DEFAULT_TECH_TRADE_LOSS_HOLES
Definition ruleload.h:84
#define RS_DEFAULT_TECH_COST_STYLE
Definition ruleload.h:90
#define RS_DEFAULT_EXTRA_APPEARANCE
Definition ruleload.h:103
#define RS_DEFAULT_TECH_PARASITE_HOLES
Definition ruleload.h:85
#define GAME_DEFAULT_ACH_VALUE
Definition ruleload.h:78
#define RS_DEFAULT_TECH_TRADE_HOLES
Definition ruleload.h:83
#define RS_DEFAULT_CULTURE_VIC_POINTS
Definition ruleload.h:94
#define RS_DEFAULT_CULTURE_MIGRATION_PML
Definition ruleload.h:96
void(* rs_conversion_logger)(const char *msg)
Definition ruleload.h:42
#define RS_DEFAULT_SMALL_WONDER_VISIBILITY
Definition ruleload.h:111
#define ruleset_error(logger, level, format,...)
Definition ruleload.h:59
#define RS_DEFAULT_ONLY_KILLING_VETERAN
Definition ruleload.h:106
#define RS_DEFAULT_TECH_LOSS_HOLES
Definition ruleload.h:86
#define RS_DEFAULT_HISTORY_INTEREST_PML
Definition ruleload.h:97
#define RS_DEFAULT_TECH_UPKEEP_STYLE
Definition ruleload.h:92
#define RS_DEFAULT_GOODS_SELECTION
Definition ruleload.h:101
#define RS_DEFAULT_PYTHAGOREAN_DIAGONAL
Definition ruleload.h:87
#define RS_DEFAULT_TECH_STEAL_HOLES
Definition ruleload.h:82
#define RS_MIN_MIN_TECH_COST
Definition ruleload.h:118
#define GAME_DEFAULT_ACH_UNIQUE
Definition ruleload.h:77
#define RS_MAX_BASE_TECH_COST
Definition ruleload.h:115
#define RS_DEFAULT_COMBAT_ODDS_SCALED_VETERANCY
Definition ruleload.h:108
#define RS_DEFAULT_MUUK_FOOD_WIPE
Definition ruleload.h:79
#define RS_DEFAULT_MUUK_GOLD_WIPE
Definition ruleload.h:80
#define RS_DEFAULT_BASE_TECH_COST
Definition ruleload.h:113
#define RS_DEFAULT_NATIONALITY
Definition ruleload.h:121
#define GAME_DEFAULT_CHANGABLE_TAX
Definition ruleload.h:74
#define RS_DEFAULT_MUUK_SHIELD_WIPE
Definition ruleload.h:81
#define RSFORMAT_CURRENT
Definition ruleload.h:38
#define RS_DEFAULT_GOLD_UPKEEP_STYLE
Definition ruleload.h:89
#define GAME_DEFAULT_ADDTOSIZE
Definition ruleload.h:73
#define RS_DEFAULT_ONLY_REAL_FIGHT_VETERAN
Definition ruleload.h:107
#define RS_DEFAULT_EXTRA_DISAPPEARANCE
Definition ruleload.h:104
#define RS_MAX_MIN_TECH_COST
Definition ruleload.h:119
#define RS_DEFAULT_MIN_TECH_COST
Definition ruleload.h:117
#define GAME_DEFAULT_VISION_REVEAL_TILES
Definition ruleload.h:75
#define RS_DEFAULT_CULTURE_VIC_LEAD
Definition ruleload.h:95
#define RS_DEFAULT_TECH_LEAKAGE
Definition ruleload.h:91
#define GAME_DEFAULT_DISASTER_FREQ
Definition ruleload.h:76
#define RSFORMAT_3_3
Definition ruleload.h:37
#define RS_MIN_BASE_TECH_COST
Definition ruleload.h:114
static struct compatibility compat[]
Definition savecompat.c:115
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:4379
sex_t sex_by_name(const char *name)
Definition sex.c:27
sex_t
Definition sex.h:20
@ SEX_UNKNOWN
Definition sex.h:21
@ SEX_FEMALE
Definition sex.h:22
@ SEX_MALE
Definition sex.h:23
bool check_strlen(const char *str, size_t len, const char *errmsg)
Definition shared.c:493
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1094
void remove_leading_trailing_spaces(char *s)
Definition shared.c:444
const struct strvec * get_data_dirs(void)
Definition shared.c:886
fc_tristate
Definition shared.h:46
@ TRI_YES
Definition shared.h:46
@ TRI_NO
Definition shared.h:46
@ TRI_MAYBE
Definition shared.h:46
#define DIR_SEPARATOR
Definition shared.h:127
#define ARRAY_SIZE(x)
Definition shared.h:85
struct specialist * specialist_by_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:2507
void update_nations_with_startpos(void)
Definition srv_main.c:2312
void strvec_store(struct strvec *psv, const char *const *vec, size_t size)
struct strvec * strvec_new(void)
bool actor_consuming_always
Definition actions.h:144
int max_distance
Definition actions.h:127
bool quiet
Definition actions.h:134
char ui_name[MAX_LEN_NAME]
Definition actions.h:130
bv_action_sub_results sub_results
Definition actions.h:115
enum action_actor_kind actor_kind
Definition actions.h:117
bv_actions blocked_by
Definition actions.h:138
enum action_target_kind target_kind
Definition actions.h:118
int min_distance
Definition actions.h:127
struct advance * require[AR_SIZE]
Definition tech.h:127
int border_sq
Definition base.h:44
int vision_main_sq
Definition base.h:45
enum base_gui_type gui_type
Definition base.h:43
int vision_invis_sq
Definition base.h:46
int vision_subs_sq
Definition base.h:47
char * nationlist
Definition game.h:289
int named_teams
Definition game.h:301
size_t as_count
Definition game.h:300
struct civ_game::@32::@36::@42 ruledit
const char ** allowed_govs
Definition game.h:292
int upgrade_veteran_loss
Definition game.h:206
struct rgbcolor * plr_bg_color
Definition game.h:103
int incite_total_factor
Definition game.h:157
int init_vis_radius_sq
Definition game.h:159
bool vision_reveal_tiles
Definition game.h:207
char * description_file
Definition game.h:288
struct packet_ruleset_control control
Definition game.h:83
char * ruleset_summary
Definition game.h:84
char ** nc_agovs
Definition game.h:293
int base_incite_cost
Definition game.h:141
bool civil_war_enabled
Definition game.h:131
int global_init_techs[MAX_NUM_TECH_LIST]
Definition game.h:110
struct packet_game_info info
Definition game.h:89
int autoupgrade_veteran_loss
Definition game.h:139
char rulesetdir[MAX_LEN_NAME]
Definition game.h:246
int start_year
Definition game.h:198
int incite_improvement_factor
Definition game.h:156
struct section_file * luadata
Definition game.h:254
char ** embedded_nations
Definition game.h:290
int global_init_buildings[MAX_NUM_BUILDING_LIST]
Definition game.h:111
struct trait_limits default_traits[TRAIT_COUNT]
Definition game.h:281
char ** nc_astyles
Definition game.h:299
const char ** allowed_terrains
Definition game.h:295
char * ruleset_description
Definition game.h:85
size_t ag_count
Definition game.h:294
const char ** allowed_styles
Definition game.h:298
bool std_tileset_compat
Definition game.h:302
struct civ_game::@31 rgame
char ** nc_aterrs
Definition game.h:296
size_t embedded_nations_count
Definition game.h:291
int incite_unit_factor
Definition game.h:158
char * ruleset_capabilities
Definition game.h:86
int ransom_gold
Definition game.h:182
struct civ_game::@32::@36 server
size_t at_count
Definition game.h:297
struct veteran_system * veteran
Definition game.h:101
struct packet_calendar_info calendar
Definition game.h:90
struct government * default_government
Definition game.h:93
struct civ_game::@32::@36::@37 deprecated
struct government * government_during_revolution
Definition game.h:94
struct civ_map::@44::@46 server
bool ocean_resources
Definition map_types.h:119
struct requirement_vector receiver_reqs
Definition diptreaty.h:61
struct requirement_vector giver_reqs
Definition diptreaty.h:60
struct requirement_vector either_reqs
Definition diptreaty.h:62
bool enabled
Definition diptreaty.h:59
enum unit_type_flag_id flag
Definition unittype.h:472
enum combat_bonus_type type
Definition unittype.h:473
struct name_translation name
Definition extras.h:90
int build_cost
Definition improvement.h:60
char graphic_str[MAX_LEN_NAME]
Definition improvement.h:55
char graphic_alt2[MAX_LEN_NAME]
Definition improvement.h:57
enum impr_genus_id genus
Definition improvement.h:63
char graphic_alt[MAX_LEN_NAME]
Definition improvement.h:56
struct requirement_vector obsolete_by
Definition improvement.h:59
char soundtag_alt[MAX_LEN_NAME]
Definition improvement.h:67
char soundtag_alt2[MAX_LEN_NAME]
Definition improvement.h:68
struct requirement_vector reqs
Definition improvement.h:58
struct strvec * helptext
Definition improvement.h:65
struct name_translation name
Definition improvement.h:52
bv_impr_flags flags
Definition improvement.h:64
char soundtag[MAX_LEN_NAME]
Definition improvement.h:66
Definition climisc.h:82
bool hidden
Definition nation.h: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
int low_firepower_pearl_harbor
bool damage_reduces_bombard_rate
int nuke_defender_survival_chance_pct
enum tech_upkeep_style tech_upkeep_style
bool tech_trade_loss_allow_holes
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
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
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_vector reqs
enum action_auto_perf_cause cause
struct requirement_vector actor_reqs
struct requirement_vector target_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
struct strvec * helptext
struct requirement_vector reqs
struct requirement_vector obs_reqs
char soundtag_alt[MAX_LEN_NAME]
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]
struct requirement_vector giver_reqs
enum clause_type type
struct requirement_vector receiver_reqs
struct requirement_vector either_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
struct strvec * helptext
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
enum counter_behavior behavior
char rule_name[MAX_LEN_NAME]
struct requirement_vector 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_vector appearance_reqs
char graphic_alt[MAX_LEN_NAME]
char act_gfx_alt2[MAX_LEN_NAME]
struct requirement_vector disappearance_reqs
bv_extra_flags flags
char act_gfx_alt[MAX_LEN_NAME]
char activity_gfx[MAX_LEN_NAME]
struct requirement_vector rmreqs
char rule_name[MAX_LEN_NAME]
enum extra_unit_seen_type eus
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 strvec * helptext
struct requirement_vector reqs
struct strvec * helptext
struct requirement_vector reqs
bv_goods_flags flags
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char helptxt[MAX_LEN_PACKET]
struct requirement_vector reqs
char name[MAX_LEN_NAME]
Multiplier_type_id id
char rule_name[MAX_LEN_NAME]
char music_combat[MAX_LEN_NAME]
struct requirement_vector 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_vector first_reqs
char rule_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
struct requirement_vector reqs
Specialist_type_id id
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]
char graphic_str[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
bv_tech_flags flags
struct strvec * helptext
struct requirement_vector research_reqs
char helptxt[MAX_LEN_PACKET]
int extra_removal_times[MAX_EXTRA_TYPES]
Terrain_type_id transform_result
int resource_freq[MAX_EXTRA_TYPES]
Resource_type_id resources[MAX_EXTRA_TYPES]
bv_terrain_flags flags
char graphic_str[MAX_LEN_NAME]
struct strvec * helptext
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 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]
struct strvec * helptext
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_vector build_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]
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:608
struct veteran_level * definitions
Definition unittype.h:502
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
void styles_alloc(int count)
Definition style.c:36
struct music_style * music_style_by_number(int id)
Definition style.c:171
int style_number(const struct nation_style *pstyle)
Definition style.c:68
void music_styles_alloc(int count)
Definition style.c:133
int style_index(const struct nation_style *pstyle)
Definition style.c:78
#define music_styles_iterate(_p)
Definition style.h:72
#define music_styles_iterate_end
Definition style.h:79
#define styles_iterate(_p)
Definition style.h:46
#define styles_iterate_end
Definition style.h:52
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
bool fc_isspace(char c)
Definition support.c:1240
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
char fc_tolower(char c)
Definition support.c:1273
#define sz_strlcpy(dest, src)
Definition support.h:195
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:146
#define fc__attribute(x)
Definition support.h:99
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct team_slot * team_slot_by_number(int team_id)
Definition team.c:175
const char * team_slot_defined_name(const struct team_slot *tslot)
Definition team.c:277
int team_slot_index(const struct team_slot *tslot)
Definition team.c:138
int team_slot_count(void)
Definition team.c:112
void team_slot_set_defined_name(struct team_slot *tslot, const char *team_name)
Definition team.c:288
#define team_slots_iterate_end
Definition team.h:77
#define team_slots_iterate(_tslot)
Definition team.h:72
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
const char * tech_flag_id_name_cb(enum tech_flag_id flag)
Definition tech.c:433
void set_user_tech_flag_name(enum tech_flag_id id, const char *name, const char *helptxt)
Definition tech.c:404
struct advance * valid_advance(struct advance *padvance)
Definition tech.c:152
void techs_precalc_data(void)
Definition tech.c:225
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
const char * tech_flag_helptxt(enum tech_flag_id id)
Definition tech.c:445
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
struct tech_class * tech_class_by_rule_name(const char *name)
Definition tech.c:361
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define tech_class_index(_ptclass_)
Definition tech.h:188
#define A_NEVER
Definition tech.h:51
#define tech_class_iterate_end
Definition tech.h:199
#define MAX_NUM_USER_TECH_FLAGS
Definition tech.h:103
#define advance_iterate_all_end
Definition tech.h:275
@ AR_TWO
Definition tech.h:107
@ AR_ROOT
Definition tech.h:108
@ AR_ONE
Definition tech.h:106
#define advance_iterate_all(_p)
Definition tech.h:274
static Tech_type_id advance_count(void)
Definition tech.h:165
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:271
#define tech_class_iterate(_p)
Definition tech.h:193
#define advance_iterate_end
Definition tech.h:272
#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:102
#define terrain_type_iterate(_p)
Definition terrain.h:266
#define T_NONE
Definition terrain.h:61
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:272
#define RESOURCE_NONE_IDENTIFIER
Definition terrain.h:52
#define RESOURCE_NULL_IDENTIFIER
Definition terrain.h:51
#define RESOURCE_FREQUENCY_MINIMUM
Definition terrain.h:100
#define MAX_NUM_TERRAINS
Definition terrain.h:69
#define T_FIRST
Definition terrain.h:65
#define MAX_NUM_USER_TER_FLAGS
Definition terrain.h:32
#define terrain_resources_iterate_end
Definition terrain.h:294
#define terrain_resources_iterate(pterrain, _res, _freq)
Definition terrain.h:285
#define RESOURCE_FREQUENCY_DEFAULT
Definition terrain.h:101
#define ACTIVITY_FACTOR
Definition tile.h:170
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:2760
const char * unit_class_flag_helptxt(enum unit_class_flag_id id)
Definition unittype.c:1858
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1771
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:203
void unit_type_action_cache_init(void)
Definition unittype.c:935
void set_unit_type_caches(struct unit_type *ptype)
Definition unittype.c:2819
void role_unit_precalcs(void)
Definition unittype.c:2179
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:2689
Unit_type_id utype_count(void)
Definition unittype.c:80
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2629
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1582
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2601
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1645
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:1788
const char * unit_type_flag_helptxt(enum unit_type_flag_id id)
Definition unittype.c:1921
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:1816
struct veteran_system * veteran_system_new(int count)
Definition unittype.c:2658
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2472
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:375
void set_user_unit_type_flag_name(enum unit_type_flag_id id, const char *name, const char *helptxt)
Definition unittype.c:1880
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:771
#define utype_class(_t_)
Definition unittype.h:754
#define combat_bonus_list_iterate_end
Definition unittype.h:487
#define L_FIRST
Definition unittype.h:354
#define combat_bonus_list_iterate(bonuslist, pbonus)
Definition unittype.h:485
#define unit_tech_reqs_iterate_end
Definition unittype.h:886
#define unit_class_iterate(_p)
Definition unittype.h:913
#define unit_tech_reqs_iterate(_utype_, _p)
Definition unittype.h:880
#define MAX_NUM_USER_UNIT_FLAGS
Definition unittype.h:336
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:622
#define UTYF_LAST_USER_FLAG
Definition unittype.h:335
#define unit_type_iterate(_p)
Definition unittype.h:860
#define U_LAST
Definition unittype.h:40
#define uclass_index(_c_)
Definition unittype.h:747
#define unit_class_iterate_end
Definition unittype.h:920
#define unit_type_iterate_end
Definition unittype.h:867
#define MAX_NUM_USER_UCLASS_FLAGS
Definition unittype.h:128