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);
210 int def, int min, int max,
211 const char *path, ...)
213
216
217/**********************************************************************/
222 const char *file, const char *function,
224 const char *format, ...)
225{
226 va_list args;
227 char buf[MAX_LEN_LOG_LINE];
228
229 if (logger == NULL && !log_do_output_for_level(level)) {
230 return;
231 }
232
233 va_start(args, format);
234 if (logger != NULL) {
235 fc_vsnprintf(buf, sizeof(buf), format, args);
236 logger(buf);
237 } else {
238 vdo_log(file, function, line, FALSE, level, buf, sizeof(buf), format, args);
239 }
240 va_end(args);
241
242 if (LOG_FATAL >= level) {
244 }
245}
246
247/**********************************************************************/
251{
252 int purged = 0;
253
254 action_iterate(act_id) {
255 struct action *paction = action_by_number(act_id);
256
258 == 0) {
259 /* Not relevant. */
260 continue;
261 }
262
263 /* Impossible hard requirement. */
265 /* Make sure that all action enablers are disabled. */
267 ae) {
268 ae->rulesave.ruledit_disabled = TRUE;
269 purged++;
271
272 log_normal("Purged all action enablers for %s",
274 }
275
276 /* Impossible requirement vector requirement. */
278 ae) {
279 if (!ae->rulesave.ruledit_disabled
281 || req_vec_is_impossible_to_fulfill(&ae->target_reqs))) {
282 ae->rulesave.ruledit_disabled = TRUE;
283 purged++;
284 log_normal("Purged unused action enabler for %s",
286 }
289
290 return purged;
291}
292
293/**********************************************************************/
297{
298 int purged = 0;
299 enum effect_type type;
300
305 eft->rulesave.do_not_save = TRUE;
306 purged++;
307 log_normal("Purged unused effect for %s",
308 effect_type_name(eft->type));
309 }
311 }
312
313 return purged;
314}
315
316/**********************************************************************/
320{
321 int purged = 0;
322
325
326 return purged;
327}
328
329/**********************************************************************/
334 const char *msg)
335{
336 struct req_vec_problem *problem;
337 bool result;
338
340 reqs);
341
342 if (problem == NULL) {
343 /* No problem. */
344 return FALSE;
345 }
346
347 if (problem->num_suggested_solutions == 0) {
348 /* No solution. */
350 return FALSE;
351 }
352
353 if (problem->num_suggested_solutions == 1
354 && problem->suggested_solutions[0].operation == RVCO_REMOVE) {
355 /* Remove !present req that never is there. */
356 log_normal("%s", msg);
357 result = req_vec_change_apply(&problem->suggested_solutions[0],
360 return result;
361 }
362
363 /* Not handled. Don't know what this is. */
364 fc_assert(problem->num_suggested_solutions == 1);
366 return FALSE;
367}
368
369/**********************************************************************/
374 const char *msg)
375{
376 struct req_vec_problem *problem;
377 bool result;
378
380 reqs);
381
382 if (problem == NULL) {
383 /* No problem. */
384 return FALSE;
385 }
386
387 if (problem->num_suggested_solutions == 0) {
388 /* No solution. */
390 return FALSE;
391 }
392
393 if (problem->num_suggested_solutions == 2
394 && problem->suggested_solutions[0].operation == RVCO_REMOVE
395 && problem->suggested_solutions[1].operation == RVCO_REMOVE
396 && are_requirements_equal(&problem->suggested_solutions[0].req,
397 &problem->suggested_solutions[1].req)) {
398 /* Simple duplication is handled. */
399 log_normal("%s", msg);
400 result = req_vec_change_apply(&problem->suggested_solutions[1],
403 return result;
404 }
405
406 /* Requirements of different kinds making each other redundant isn't
407 * supported yet. It could be done by always removing the most general
408 * requirement. So unit type is kept when redundant with unit flag, unit
409 * class and unit class flag etc. */
411 return FALSE;
412}
413
414/**********************************************************************/
419 const char *msg)
420{
421 return (purge_unused_req_vec(reqs, msg)
423}
424
425/**********************************************************************/
430{
431 int purged = 0;
432
433 action_iterate(act_id) {
434 struct action *paction = action_by_number(act_id);
435 char actor_reqs[MAX_LEN_NAME * 2];
436 char target_reqs[MAX_LEN_NAME * 2];
437
438 /* Error log text */
439 fc_snprintf(actor_reqs, sizeof(actor_reqs),
440 "Purged redundant requirement in"
441 " %s in action enabler for %s",
442 "actor_reqs", action_rule_name(paction));
443 fc_snprintf(target_reqs, sizeof(target_reqs),
444 "Purged redundant requirement in"
445 " %s in action enabler for %s",
446 "target_reqs", action_rule_name(paction));
447
448 /* Do the purging. */
450 ae) {
451 while (!ae->rulesave.ruledit_disabled
452 && (purge_redundant_req_vec(&ae->actor_reqs, actor_reqs)
453 || purge_redundant_req_vec(&ae->target_reqs,
454 target_reqs))) {
455 purged++;
456 }
459
460 return purged;
461}
462
463/**********************************************************************/
468{
469 int purged = 0;
470 enum effect_type type;
471
474 char msg[MAX_LEN_NAME * 2];
475
476 /* Error log text */
477 fc_snprintf(msg, sizeof(msg),
478 "Purged redundant requirement in effect of type %s",
480
481 /* Do the purging. */
483 while (purge_redundant_req_vec(&eft->reqs, msg)) {
484 purged++;
485 }
487 }
488
489 return purged;
490}
491
492/**********************************************************************/
497{
498 int purged = 0;
499
502
503 if (purged > 0) {
504 /* An unused requirement may be an obligatory hard requirement. */
506 }
507
508 return purged;
509}
510
511/**********************************************************************/
515static const char *valid_ruleset_filename(const char *subdir,
516 const char *name,
517 const char *extension,
518 bool optional)
519{
520 char filename[512];
521 const char *dfilename;
522
524
525 fc_snprintf(filename, sizeof(filename), "%s" DIR_SEPARATOR "%s.%s",
527 log_verbose("Trying \"%s\".", filename);
528 dfilename = fileinfoname(get_data_dirs(), filename);
529 if (dfilename) {
530 return dfilename;
531 }
532
533 fc_snprintf(filename, sizeof(filename), "default" DIR_SEPARATOR "%s.%s", name, extension);
534 log_verbose("Trying \"%s\": default ruleset directory.", filename);
535 dfilename = fileinfoname(get_data_dirs(), filename);
536 if (dfilename) {
537 return dfilename;
538 }
539
540 fc_snprintf(filename, sizeof(filename), "%s_%s.%s",
542 log_verbose("Trying \"%s\": alternative ruleset filename syntax.",
543 filename);
544 dfilename = fileinfoname(get_data_dirs(), filename);
545 if (dfilename) {
546 return dfilename;
547 } else if (!optional) {
549 /* TRANS: message about an installation error. */
550 _("Could not find a readable \"%s.%s\" ruleset file."),
551 name, extension);
552 }
553
554 return NULL;
555}
556
557/**********************************************************************/
561{
562 return script_buffer;
563}
564
565/**********************************************************************/
569{
570 return parser_buffer;
571}
572
573/**********************************************************************/
577static struct section_file *openload_ruleset_file(const char *whichset,
578 const char *rsdir)
579{
580 char sfilename[512];
583 struct section_file *secfile;
584
585 if (dfilename == NULL) {
586 return NULL;
587 }
588
589 /* Need to save a copy of the filename for following message, since
590 section_file_load() may call datafilename() for includes. */
592 secfile = secfile_load(sfilename, FALSE);
593
594 if (secfile == NULL) {
595 ruleset_error(NULL, LOG_ERROR, "Could not load ruleset '%s':\n%s",
597 }
598
599 return secfile;
600}
601
602/**********************************************************************/
605static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir,
606 char **buffer, bool optional)
607{
610
611 if (dfilename == NULL) {
612 return optional ? TRI_MAYBE : TRI_NO;
613 }
614
615 if (buffer == NULL) {
617 ruleset_error(NULL, LOG_ERROR, "\"%s\": could not load ruleset script.",
618 dfilename);
619
620 return TRI_NO;
621 }
622 } else {
624 }
625
626 return TRI_YES;
627}
628
629/**********************************************************************/
632static struct section_file *openload_luadata_file(const char *rsdir)
633{
634 struct section_file *secfile;
635 char sfilename[512];
636 const char *dfilename = valid_ruleset_filename(rsdir, "luadata",
637 "txt", TRUE);
638
639 if (dfilename == NULL) {
640 return NULL;
641 }
642
643 /* Need to save a copy of the filename for following message, since
644 section_file_load() may call datafilename() for includes. */
646 secfile = secfile_load(sfilename, FALSE);
647
648 if (secfile == NULL) {
649 ruleset_error(NULL, LOG_ERROR, "Could not load luadata '%s':\n%s",
651 }
652
653 return secfile;
654}
655
656/**********************************************************************/
661 struct rscompat_info *compat,
662 const char *sec,
663 const char *sub,
664 const char *rfor)
665{
666 const char *type, *name;
667 int j;
668 const char *filename;
669
670 filename = secfile_name(file);
671
673
674 for (j = 0; (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
675 sec, sub, j)); j++) {
676 char buf[MAX_LEN_NAME];
677 const char *range;
678 bool survives, present, quiet;
679 struct entry *pentry;
680 struct requirement req;
681
682 if (!(pentry = secfile_entry_lookup(file, "%s.%s%d.name",
683 sec, sub, j))) {
685
686 return NULL;
687 }
688 name = NULL;
689 switch (entry_type_get(pentry)) {
690 case ENTRY_BOOL:
691 {
692 bool val;
693
694 if (entry_bool_get(pentry, &val)) {
695 fc_snprintf(buf, sizeof(buf), "%d", val);
696 name = buf;
697 }
698 }
699 break;
700 case ENTRY_INT:
701 {
702 int val;
703
704 if (entry_int_get(pentry, &val)) {
705 fc_snprintf(buf, sizeof(buf), "%d", val);
706 name = buf;
707 }
708 }
709 break;
710 case ENTRY_STR:
712 break;
713 case ENTRY_FLOAT:
716 "\"%s\": trying to have an floating point entry as a requirement name in '%s.%s%d'.",
717 filename, sec, sub, j);
718 break;
721 break;
724 break;
725 case ENTRY_ILLEGAL:
727 break;
728 }
729 if (NULL == name) {
731 "\"%s\": error in handling requirement name for '%s.%s%d'.",
732 filename, sec, sub, j);
733 return NULL;
734 }
735
736 if (!(range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j))) {
738
739 return NULL;
740 }
741
742 survives = FALSE;
743 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.survives",
744 sec, sub, j))
747 "\"%s\": invalid boolean value for survives for "
748 "'%s.%s%d'.", filename, sec, sub, j);
749 }
750
751 present = TRUE;
752 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.present",
753 sec, sub, j))
756 "\"%s\": invalid boolean value for present for "
757 "'%s.%s%d'.", filename, sec, sub, j);
758 }
759 quiet = FALSE;
760 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.quiet",
761 sec, sub, j))
762 && !entry_bool_get(pentry, &quiet)) {
764 "\"%s\": invalid boolean value for quiet for "
765 "'%s.%s%d'.", filename, sec, sub, j);
766 }
767
768 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
770 }
771
773 if (req.source.kind == universals_n_invalid()) {
775 "\"%s\" [%s] has invalid or unknown req: "
776 "\"%s\" \"%s\".",
777 filename, sec, type, name);
778
779 return NULL;
780 }
781
783 }
784
785 return &reqs_list;
786}
787
788/**********************************************************************/
792 struct section_file *file,
793 const char *sec,
794 const char *sub)
795{
796 const char *flag;
797 int j;
798 const char *filename;
799 bool success = TRUE;
800
801 filename = secfile_name(file);
802
803 for (j = 0; (flag = secfile_lookup_str_default(file, NULL, "%s.%s%d.flag",
804 sec, sub, j)); j++) {
805 struct combat_bonus *bonus = fc_malloc(sizeof(*bonus));
806 const char *type;
807
809 if (!unit_type_flag_id_is_valid(bonus->flag)) {
810 log_error("\"%s\": unknown flag name \"%s\" in '%s.%s'.",
811 filename, flag, sec, sub);
812 FC_FREE(bonus);
813 success = FALSE;
814 continue;
815 }
816 type = secfile_lookup_str(file, "%s.%s%d.type", sec, sub, j);
818 if (!combat_bonus_type_is_valid(bonus->type)) {
819 log_error("\"%s\": unknown bonus type \"%s\" in '%s.%s'.",
820 filename, type, sec, sub);
821 FC_FREE(bonus);
822 success = FALSE;
823 continue;
824 }
825 if (!secfile_lookup_int(file, &bonus->value, "%s.%s%d.value",
826 sec, sub, j)) {
827 log_error("\"%s\": failed to get value from '%s.%s%d'.",
828 filename, sec, sub, j);
829 FC_FREE(bonus);
830 success = FALSE;
831 continue;
832 }
834 "%s.%s%d.quiet",
835 sec, sub, j);
837 }
838
839 return success;
840}
841
842/**********************************************************************/
850static bool lookup_tech(struct section_file *file,
851 struct advance **result,
852 const char *prefix, const char *entry,
853 const char *filename,
854 const char *description)
855{
856 const char *sval;
857
858 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
859 if (!sval || !strcmp(sval, "Never")) {
860 *result = A_NEVER;
861 } else {
862 *result = advance_by_rule_name(sval);
863
864 if (A_NEVER == *result) {
866 "\"%s\" %s %s: couldn't match \"%s\".",
867 filename, (description ? description : prefix), entry, sval);
868 return FALSE;
869 }
870 }
871
872 return TRUE;
873}
874
875/**********************************************************************/
882static bool lookup_unit_list(struct section_file *file, const char *prefix,
883 const char *entry,
884 struct unit_type **output,
885 const char *filename)
886{
887 const char **slist;
888 size_t nval;
889 int i;
890 bool ok = TRUE;
891
892 /* pre-fill with NULL: */
893 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
894 output[i] = NULL;
895 }
896 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
897 if (nval == 0) {
898 /* 'No vector' is considered same as empty vector */
899 if (slist != NULL) {
900 free(slist);
901 }
902 return TRUE;
903 }
904 if (nval > MAX_NUM_UNIT_LIST) {
906 "\"%s\": string vector %s.%s too long (%d, max %d)",
907 filename, prefix, entry, (int) nval, MAX_NUM_UNIT_LIST);
908 ok = FALSE;
909 } else if (nval == 1 && strcmp(slist[0], "") == 0) {
910 free(slist);
911 return TRUE;
912 }
913 if (ok) {
914 for (i = 0; i < nval; i++) {
915 const char *sval = slist[i];
917
918 if (!punittype) {
920 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
921 filename, prefix, entry, i, sval);
922 ok = FALSE;
923 break;
924 }
925 output[i] = punittype;
926 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
928 }
929 }
930 free(slist);
931
932 return ok;
933}
934
935/**********************************************************************/
942static bool lookup_tech_list(struct section_file *file, const char *prefix,
943 const char *entry, int *output,
944 const char *filename)
945{
946 const char **slist;
947 size_t nval;
948 int i;
949 bool ok = TRUE;
950
951 /* pre-fill with A_LAST: */
952 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
953 output[i] = A_LAST;
954 }
955 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
956 if (slist == NULL || nval == 0) {
957 return TRUE;
958 } else if (nval > MAX_NUM_TECH_LIST) {
960 "\"%s\": string vector %s.%s too long (%d, max %d)",
961 filename, prefix, entry, (int) nval, MAX_NUM_TECH_LIST);
962 ok = FALSE;
963 }
964
965 if (ok) {
966 if (nval == 1 && strcmp(slist[0], "") == 0) {
967 FC_FREE(slist);
968 return TRUE;
969 }
970 for (i = 0; i < nval && ok; i++) {
971 const char *sval = slist[i];
973
974 if (NULL == padvance) {
976 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
977 filename, prefix, entry, i, sval);
978 ok = FALSE;
979 }
980 if (!valid_advance(padvance)) {
982 "\"%s\" %s.%s (%d): \"%s\" is removed.",
983 filename, prefix, entry, i, sval);
984 ok = FALSE;
985 }
986
987 if (ok) {
988 output[i] = advance_number(padvance);
989 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
991 }
992 }
993 }
994 FC_FREE(slist);
995
996 return ok;
997}
998
999/**********************************************************************/
1006static bool lookup_building_list(struct section_file *file,
1007 const char *prefix, const char *entry,
1008 int *output, const char *filename)
1009{
1010 const char **slist;
1011 size_t nval;
1012 int i;
1013 bool ok = TRUE;
1014
1015 /* pre-fill with B_LAST: */
1016 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
1017 output[i] = B_LAST;
1018 }
1019 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
1022 "\"%s\": string vector %s.%s too long (%d, max %d)",
1023 filename, prefix, entry, (int) nval, MAX_NUM_BUILDING_LIST);
1024 ok = FALSE;
1025 } else if (nval == 0 || (nval == 1 && strcmp(slist[0], "") == 0)) {
1026 if (slist != NULL) {
1027 FC_FREE(slist);
1028 }
1029 return TRUE;
1030 }
1031 if (ok) {
1032 for (i = 0; i < nval; i++) {
1033 const char *sval = slist[i];
1034 struct impr_type *pimprove = improvement_by_rule_name(sval);
1035
1036 if (NULL == pimprove) {
1038 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1039 filename, prefix, entry, i, sval);
1040 ok = FALSE;
1041 break;
1042 }
1043 output[i] = improvement_number(pimprove);
1044 log_debug("%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
1045 }
1046 }
1047 free(slist);
1048
1049 return ok;
1050}
1051
1052/**********************************************************************/
1058static bool lookup_unit_type(struct section_file *file,
1059 const char *prefix,
1060 const char *entry,
1061 const struct unit_type **result,
1062 const char *filename,
1063 const char *description)
1064{
1065 const char *sval;
1066
1067 sval = secfile_lookup_str_default(file, "None", "%s.%s", prefix, entry);
1068
1069 if (strcmp(sval, "None") == 0) {
1070 *result = NULL;
1071 } else {
1072 *result = unit_type_by_rule_name(sval);
1073 if (*result == NULL) {
1075 "\"%s\" %s %s: couldn't match \"%s\".",
1076 filename, (description ? description : prefix), entry, sval);
1077
1078 return FALSE;
1079 }
1080 }
1081
1082 return TRUE;
1083}
1084
1085/**********************************************************************/
1089static struct government *lookup_government(struct section_file *file,
1090 const char *entry,
1091 const char *filename,
1092 struct government *fallback)
1093{
1094 const char *sval;
1095 struct government *gov;
1096
1097 sval = secfile_lookup_str_default(file, NULL, "%s", entry);
1098 if (!sval) {
1099 gov = fallback;
1100 } else {
1102 }
1103 if (!gov) {
1105 "\"%s\" %s: couldn't match \"%s\".",
1106 filename, entry, sval);
1107 }
1108 return gov;
1109}
1110
1111/**********************************************************************/
1114static char *lookup_string(struct section_file *file, const char *prefix,
1115 const char *suffix)
1116{
1117 const char *sval = secfile_lookup_str(file, "%s.%s", prefix, suffix);
1118
1119 if (NULL != sval) {
1120 char copy[strlen(sval) + 1];
1121
1122 strcpy(copy, sval);
1124 if (strlen(copy) > 0) {
1125 return fc_strdup(copy);
1126 }
1127 }
1128 return NULL;
1129}
1130
1131/**********************************************************************/
1134static struct strvec *lookup_strvec(struct section_file *file,
1135 const char *prefix, const char *suffix)
1136{
1137 size_t dim;
1138 const char **vec = secfile_lookup_str_vec(file, &dim,
1139 "%s.%s", prefix, suffix);
1140
1141 if (NULL != vec) {
1142 struct strvec *dest = strvec_new();
1143
1144 strvec_store(dest, vec, dim);
1145 free(vec);
1146 return dest;
1147 }
1148 return NULL;
1149}
1150
1151/**********************************************************************/
1154static struct extra_type *lookup_resource(const char *filename,
1155 const char *name,
1156 const char *jsection)
1157{
1158 struct extra_type *pres;
1159
1161
1162 if (pres == NULL) {
1164 "\"%s\" [%s] has unknown \"%s\".",
1165 filename, jsection, name);
1166 }
1167
1168 return pres;
1169}
1170
1171/**********************************************************************/
1175static bool lookup_terrain(struct section_file *file,
1176 const char *entry,
1177 const char *filename,
1178 struct terrain *pthis,
1179 struct terrain **result,
1180 bool null_acceptable)
1181{
1182 const int j = terrain_index(pthis);
1183 const char *jsection = &terrain_sections[j * MAX_SECTION_LABEL];
1184 const char *name = secfile_lookup_str(file, "%s.%s", jsection, entry);
1185 struct terrain *pterr;
1186
1187 if (NULL == name && !null_acceptable) {
1188 return FALSE;
1189 }
1190
1191 if (NULL == name
1192 || *name == '\0'
1193 || (0 == strcmp(name, "none"))
1194 || (0 == strcmp(name, "no"))) {
1195 *result = T_NONE;
1196
1197 return TRUE;
1198 }
1199 if (0 == strcmp(name, "yes")) {
1200 *result = pthis;
1201
1202 return TRUE;
1203 }
1204
1206 *result = pterr;
1207
1208 if (pterr == NULL) {
1210 "\"%s\" [%s] has unknown \"%s\".",
1211 secfile_name(file), jsection, name);
1212 return FALSE;
1213 }
1214
1215 return TRUE;
1216}
1217
1218/**********************************************************************/
1225static bool lookup_time(const struct section_file *secfile, int *turns,
1226 const char *sec_name, const char *property_name,
1227 const char *filename, const char *item_name,
1228 bool *ok)
1229{
1230 /* Assumes that PACKET_UNIT_INFO.activity_count in packets.def is UINT16 */
1231 const int max_turns = 65535 / ACTIVITY_FACTOR;
1232
1233 if (!secfile_lookup_int(secfile, turns, "%s.%s", sec_name, property_name)) {
1234 return FALSE;
1235 }
1236
1237 if (*turns > max_turns) {
1239 "\"%s\": \"%s\": \"%s\" value %d too large (max %d)",
1240 filename, item_name ? item_name : sec_name,
1241 property_name, *turns, max_turns);
1242 *ok = FALSE;
1243 }
1244
1245 return TRUE; /* we found _something */
1246}
1247
1248/**********************************************************************/
1252 const char *domain,
1253 struct section_file *file,
1254 const char *sec_name)
1255{
1256 const char *name = secfile_lookup_str(file, "%s.name", sec_name);
1257 const char *rule_name = secfile_lookup_str(file, "%s.rule_name", sec_name);
1258
1259 if (!name) {
1261 "\"%s\" [%s]: no \"name\" specified.",
1262 secfile_name(file), sec_name);
1263 return FALSE;
1264 }
1265
1266 names_set(pname, domain, name, rule_name);
1267
1268 return TRUE;
1269}
1270
1271/**********************************************************************/
1275 struct section_file *file,
1276 const char *secname, const char *field_prefix)
1277{
1278 enum trait tr;
1279
1280 /* FIXME: Use specenum trait names without duplicating them here.
1281 * Just needs to take care of case.
1282 * This list is also duplicated in rulesave.c:save_traits() */
1283 const char *trait_names[] = {
1284 "expansionist",
1285 "trader",
1286 "aggressive",
1287 "builder",
1288 NULL
1289 };
1290
1291 for (tr = trait_begin(); tr != trait_end() && trait_names[tr] != NULL; tr = trait_next(tr)) {
1292 out[tr].min = secfile_lookup_int_default(file, -1, "%s.%s%s_min",
1293 secname,
1295 trait_names[tr]);
1296 out[tr].max = secfile_lookup_int_default(file, -1, "%s.%s%s_max",
1297 secname,
1299 trait_names[tr]);
1300 out[tr].fixed = secfile_lookup_int_default(file, -1, "%s.%s%s_default",
1301 secname,
1303 trait_names[tr]);
1304 }
1305
1306 fc_assert(tr == trait_end()); /* number of trait_names correct */
1307}
1308
1309/**********************************************************************/
1313static bool load_game_names(struct section_file *file,
1314 struct rscompat_info *compat)
1315{
1316 struct section_list *sec;
1317 int nval;
1318 const char *filename = secfile_name(file);
1319 bool ok = TRUE;
1320
1321 /* section: datafile */
1323 if (compat->version <= 0) {
1324 return FALSE;
1325 }
1326
1327 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1328 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1329
1331 nval = (NULL != sec ? section_list_size(sec) : 0);
1333 int num = nval; /* No "size_t" to printf */
1334
1336 "\"%s\": Too many achievement types (%d, max %d)",
1337 filename, num, MAX_ACHIEVEMENT_TYPES);
1338 ok = FALSE;
1339 } else {
1341 }
1342
1343 if (ok) {
1346
1347 if (!ruleset_load_names(&pach->name, NULL, file, sec_name)) {
1349 "\"%s\": Cannot load achievement names",
1350 filename);
1351 ok = FALSE;
1352 break;
1353 }
1355 }
1356
1358
1359 if (ok) {
1361
1362 nval = (NULL != sec ? section_list_size(sec) : 0);
1363 if (nval > MAX_GOODS_TYPES) {
1364 int num = nval; /* No "size_t" to printf */
1365
1367 "\"%s\": Too many goods types (%d, max %d)",
1368 filename, num, MAX_GOODS_TYPES);
1370 ok = FALSE;
1371 } else if (nval < 1) {
1373 "\"%s\": At least one goods type needed",
1374 filename);
1376 ok = FALSE;
1377 } else {
1379 }
1380
1381 if (ok) {
1383 const char *sec_name
1385
1386 if (!ruleset_load_names(&pgood->name, NULL, file, sec_name)) {
1388 "\"%s\": Cannot load goods names",
1389 filename);
1390 ok = FALSE;
1391 break;
1392 }
1394 }
1396 }
1397
1398 if (ok) {
1399
1401
1402 nval = (NULL != sec ? section_list_size(sec) : 0);
1403 if (nval > MAX_COUNTERS) {
1404 size_t num = nval;
1405
1407 "\"%s\": Too many counters (" SIZE_T_PRINTF ", max %d)",
1408 filename, num, MAX_COUNTERS);
1409 ok = FALSE;
1410 }
1411
1412 if (ok) {
1413 int count_idx;
1414
1416
1417 for (count_idx = 0; count_idx < nval; count_idx++) {
1418
1420 const char *sec_name
1422
1423 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
1425 "\"%s\": Cannot load counters names",
1426 filename);
1427 ok = FALSE;
1428 break;
1429 }
1430 }
1431 }
1432
1434 }
1435
1436 return ok;
1437}
1438
1439/**********************************************************************/
1443static bool load_action_names(struct section_file *file,
1444 struct rscompat_info *compat)
1445{
1446 const char *filename = secfile_name(file);
1447 bool ok = TRUE;
1448
1449 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1450 return FALSE;
1451 }
1452
1453 (void) secfile_entry_by_path(file, "datafile.description"); /* Unused */
1454 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* Unused */
1455
1456 return ok;
1457}
1458
1459/**********************************************************************/
1463static bool load_tech_names(struct section_file *file,
1464 struct rscompat_info *compat)
1465{
1466 struct section_list *sec = NULL;
1467 /* Number of techs in the ruleset (means without A_NONE). */
1468 int num_techs = 0;
1469 int i;
1470 const char *filename = secfile_name(file);
1471 bool ok = TRUE;
1472 const char *flag;
1473
1474 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1475 return FALSE;
1476 }
1477
1478 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1479 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1480
1481 /* User tech flag names */
1482 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1483 i++) {
1484 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1485 i);
1488 "\"%s\": Duplicate tech flag name '%s'",
1489 filename, flag);
1490 ok = FALSE;
1491 break;
1492 }
1493 if (i > MAX_NUM_USER_TECH_FLAGS) {
1495 "\"%s\": Too many user tech flags!",
1496 filename);
1497 ok = FALSE;
1498 break;
1499 }
1500
1501 set_user_tech_flag_name(TECH_USER_1 + i, flag, helptxt);
1502 }
1503
1504 if (ok) {
1505 size_t nval;
1506
1507 for (; i < MAX_NUM_USER_TECH_FLAGS; i++) {
1509 }
1510
1511 /* Tech classes */
1513
1514 nval = (NULL != sec ? section_list_size(sec) : 0);
1515 if (nval > MAX_NUM_TECH_CLASSES) {
1516 int num = nval; /* No "size_t" to printf */
1517
1519 "\"%s\": Too many tech classes (%d, max %d)",
1520 filename, num, MAX_NUM_TECH_CLASSES);
1522 ok = FALSE;
1523 } else {
1525 }
1526
1527 if (ok) {
1529 const char *sec_name
1531
1532 if (!ruleset_load_names(&ptclass->name, NULL, file, sec_name)) {
1533 ruleset_error(NULL, LOG_ERROR, "\"%s\": Cannot load tech class names",
1534 filename);
1535 ok = FALSE;
1536 break;
1537 }
1539 }
1540 }
1541
1542 if (ok) {
1543 /* The techs: */
1545 if (NULL == sec || 0 == (num_techs = section_list_size(sec))) {
1547 "\"%s\": No Advances?!?", filename);
1548 ok = FALSE;
1549 } else {
1550 log_verbose("%d advances (including possibly unused)", num_techs);
1551 if (num_techs + A_FIRST > A_LAST) {
1553 "\"%s\": Too many advances (%d, max %d)",
1554 filename, num_techs, A_LAST - A_FIRST);
1555 ok = FALSE;
1556 }
1557 }
1558 }
1559
1560 if (ok) {
1561 game.control.num_tech_types = num_techs + A_FIRST; /* includes A_NONE */
1562
1563 i = 0;
1564 advance_iterate(adv) {
1565 if (!ruleset_load_names(&adv->name, NULL, file,
1567 ok = FALSE;
1568 break;
1569 }
1570 i++;
1572 }
1574
1575 return ok;
1576}
1577
1578/**********************************************************************/
1581static bool load_ruleset_techs(struct section_file *file,
1582 struct rscompat_info *compat)
1583{
1584 struct section_list *sec;
1585 const char **slist;
1586 int i;
1587 size_t nval;
1589 const char *filename = secfile_name(file);
1590 bool ok = TRUE;
1591
1593
1594 i = 0;
1596 const char *sec_name = section_name(section_list_get(sec, i));
1597
1598 ptclass->cost_pct = secfile_lookup_int_default(file, 100, "%s.%s",
1599 sec_name, "cost_pct");
1600
1601 i++;
1603
1605
1606 i = 0;
1607 advance_iterate(a) {
1608 const char *sec_name = section_name(section_list_get(sec, i));
1609 const char *sval;
1610 int j, ival;
1611 struct requirement_vector *research_reqs;
1612
1613 if (!lookup_tech(file, &a->require[AR_ONE], sec_name, "req1",
1614 filename, rule_name_get(&a->name))
1615 || !lookup_tech(file, &a->require[AR_TWO], sec_name, "req2",
1616 filename, rule_name_get(&a->name))
1617 || !lookup_tech(file, &a->require[AR_ROOT], sec_name, "root_req",
1618 filename, rule_name_get(&a->name))) {
1619 ok = FALSE;
1620 break;
1621 }
1622
1623 if ((A_NEVER == a->require[AR_ONE] && A_NEVER != a->require[AR_TWO])
1624 || (A_NEVER != a->require[AR_ONE] && A_NEVER == a->require[AR_TWO])) {
1626 "\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
1627 filename, sec_name, rule_name_get(&a->name));
1628 ok = FALSE;
1629 break;
1630 }
1631 if (a_none == a->require[AR_ONE] && a_none != a->require[AR_TWO]) {
1633 "\"%s\" [%s] \"%s\": should have \"None\" second.",
1634 filename, sec_name, rule_name_get(&a->name));
1635 ok = FALSE;
1636 break;
1637 }
1638
1639 if (game.control.num_tech_classes == 0) {
1640 a->tclass = NULL;
1641 } else {
1642 const char *classname;
1643
1644 classname = lookup_string(file, sec_name, "class");
1645 if (classname != NULL) {
1648 if (a->tclass == NULL) {
1650 "\"%s\" [%s] \"%s\": Unknown tech class \"%s\".",
1651 filename, sec_name, rule_name_get(&a->name), classname);
1652 ok = FALSE;
1653 break;
1654 }
1655 } else {
1656 a->tclass = NULL; /* Default */
1657 }
1658 }
1659
1660 research_reqs = lookup_req_list(file, compat, sec_name, "research_reqs",
1661 rule_name_get(&a->name));
1662 if (research_reqs == NULL) {
1663 ok = FALSE;
1664 break;
1665 }
1666
1667 requirement_vector_copy(&a->research_reqs, research_reqs);
1668
1669 BV_CLR_ALL(a->flags);
1670
1671 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
1672 for (j = 0; j < nval; j++) {
1673 sval = slist[j];
1674 if (strcmp(sval, "") == 0) {
1675 continue;
1676 }
1680 "\"%s\" [%s] \"%s\": bad flag name \"%s\".",
1681 filename, sec_name, rule_name_get(&a->name), sval);
1682 ok = FALSE;
1683 break;
1684 } else {
1685 BV_SET(a->flags, ival);
1686 }
1687 }
1688 free(slist);
1689
1690 if (!ok) {
1691 break;
1692 }
1693
1694 sz_strlcpy(a->graphic_str,
1695 secfile_lookup_str_default(file, "-", "%s.graphic", sec_name));
1696 sz_strlcpy(a->graphic_alt,
1698 "%s.graphic_alt", sec_name));
1699
1700 a->helptext = lookup_strvec(file, sec_name, "helptext");
1701 a->bonus_message = lookup_string(file, sec_name, "bonus_message");
1702 a->cost = secfile_lookup_int_default(file, -1, "%s.%s",
1703 sec_name, "cost");
1704 a->num_reqs = 0;
1705
1706 i++;
1708
1709 /* Propagate a root tech up into the tech tree. If a technology
1710 * X has Y has a root tech, then any technology requiring X (in the
1711 * normal way or as a root tech) also has Y as a root tech.
1712 * Later techs may gain a whole set of root techs in this way. The one
1713 * we store in AR_ROOT is a more or less arbitrary one of these,
1714 * also signalling that the set is non-empty; after this, you'll still
1715 * have to walk the tech tree to find them all. */
1716restart:
1717
1718 if (ok) {
1719 advance_iterate(a) {
1720 if (valid_advance(a)
1721 && A_NEVER != a->require[AR_ROOT]) {
1722 bool out_of_order = FALSE;
1723
1724 /* Now find any tech depending on this technology and update its
1725 * root_req. */
1726 advance_iterate(b) {
1727 if (valid_advance(b)
1728 && A_NEVER == b->require[AR_ROOT]
1729 && (a == b->require[AR_ONE] || a == b->require[AR_TWO])) {
1730 b->require[AR_ROOT] = a->require[AR_ROOT];
1731 b->inherited_root_req = TRUE;
1732 if (b < a) {
1734 }
1735 }
1737
1738 if (out_of_order) {
1739 /* HACK: If we just changed the root_tech of a lower-numbered
1740 * technology, we need to go back so that we can propagate the
1741 * root_tech up to that technology's parents... */
1742 goto restart;
1743 }
1744 }
1746
1747 /* Now rename A_NEVER to A_NONE for consistency */
1749 if (A_NEVER == a->require[AR_ROOT]) {
1750 a->require[AR_ROOT] = a_none;
1751 }
1753
1754 /* Some more consistency checking:
1755 Non-removed techs depending on removed techs is too
1756 broken to fix by default, so die.
1757 */
1758 advance_iterate(a) {
1759 if (valid_advance(a)) {
1760 /* We check for recursive tech loops later,
1761 * in build_required_techs_helper. */
1762 if (!valid_advance(a->require[AR_ONE])) {
1764 "\"%s\" tech \"%s\": req1 leads to removed tech.",
1765 filename, advance_rule_name(a));
1766 ok = FALSE;
1767 break;
1768 }
1769 if (!valid_advance(a->require[AR_TWO])) {
1771 "\"%s\" tech \"%s\": req2 leads to removed tech.",
1772 filename, advance_rule_name(a));
1773 ok = FALSE;
1774 break;
1775 }
1776 }
1778 }
1779
1781 if (ok) {
1783 }
1784
1785 return ok;
1786}
1787
1788/**********************************************************************/
1792static bool load_unit_names(struct section_file *file,
1793 struct rscompat_info *compat)
1794{
1795 struct section_list *sec = NULL;
1796 int nval = 0;
1797 int i;
1798 const char *filename = secfile_name(file);
1799 const char *flag;
1800 bool ok = TRUE;
1801
1802 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1803 return FALSE;
1804 }
1805
1806 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1807 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1808
1809 /* User unit flag names */
1810 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1811 i++) {
1812 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1813 i);
1814
1818 "\"%s\": Duplicate unit flag name '%s'",
1819 filename, flag);
1820 ok = FALSE;
1821 break;
1822 }
1823 if (i > MAX_NUM_USER_UNIT_FLAGS) {
1825 "\"%s\": Too many user unit type flags!",
1826 filename);
1827 ok = FALSE;
1828 break;
1829 }
1830
1832 }
1833
1834 if (ok) {
1835 /* Blank the remaining unit type user flags. */
1836 for (; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
1838 }
1839 }
1840
1841 if (ok) {
1842 /* User unit class flag names */
1843 for (i = 0;
1844 (flag = secfile_lookup_str_default(file, NULL,
1845 "control.class_flags%d.name",
1846 i));
1847 i++) {
1848 const char *helptxt = secfile_lookup_str_default(file, NULL,
1849 "control.class_flags%d.helptxt", i);
1850
1854 "\"%s\": Duplicate unit class flag name '%s'",
1855 filename, flag);
1856 ok = FALSE;
1857 break;
1858 }
1861 "\"%s\": Too many user unit class flags!",
1862 filename);
1863 ok = FALSE;
1864 break;
1865 }
1866
1868 }
1869 }
1870
1871 if (ok) {
1872 /* Blank the remaining unit class user flags. */
1873 for (; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
1875 }
1876 }
1877
1878 if (ok) {
1879 /* Unit classes */
1881 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1883 "\"%s\": No unit classes?!?", filename);
1884 ok = FALSE;
1885 } else {
1886 log_verbose("%d unit classes", nval);
1887 if (nval > UCL_LAST) {
1889 "\"%s\": Too many unit classes (%d, max %d)",
1890 filename, nval, UCL_LAST);
1891 ok = FALSE;
1892 }
1893 }
1894 }
1895
1896 if (ok) {
1898
1900 const int pci = uclass_index(punitclass);
1901
1902 if (!ruleset_load_names(&punitclass->name, NULL, file,
1904 ok = FALSE;
1905 break;
1906 }
1908 }
1910 sec = NULL;
1911
1912 /* The names: */
1913 if (ok) {
1915 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1917 "\"%s\": No unit types?!?", filename);
1918 ok = FALSE;
1919 } else {
1920 log_verbose("%d unit types (including possibly unused)", nval);
1921 if (nval > U_LAST) {
1923 "\"%s\": Too many unit types (%d, max %d)",
1924 filename, nval, U_LAST);
1925 ok = FALSE;
1926 }
1927 }
1928 }
1929
1930 if (ok) {
1932
1934 const int utypei = utype_index(punittype);
1935 if (!ruleset_load_names(&punittype->name, NULL, file,
1937 ok = FALSE;
1938 break;
1939 }
1941 }
1943
1944 return ok;
1945}
1946
1947/**********************************************************************/
1950static bool load_ruleset_veteran(struct section_file *file,
1951 const char *path,
1952 struct veteran_system **vsystem, char *err,
1953 size_t err_len)
1954{
1955 const char **vlist_name;
1958 int i;
1959 bool ret = TRUE;
1960
1961 /* The pointer should be uninitialised. */
1962 if (*vsystem != NULL) {
1963 fc_snprintf(err, err_len, "Veteran system is defined?!");
1964 return FALSE;
1965 }
1966
1967 /* Load data. */
1969 "%s.veteran_names", path);
1971 "%s.veteran_power_fact", path);
1973 "%s.veteran_base_raise_chance", path);
1975 "%s.veteran_work_raise_chance",
1976 path);
1978 "%s.veteran_move_bonus", path);
1979
1980 if (count_name > MAX_VET_LEVELS) {
1981 ret = FALSE;
1982 fc_snprintf(err, err_len, "\"%s\": Too many veteran levels (section "
1983 "'%s': %lu, max %d)", secfile_name(file), path,
1984 (long unsigned)count_name, MAX_VET_LEVELS);
1985 } else if (count_name != count_power
1988 || count_name != count_move) {
1989 ret = FALSE;
1990 fc_snprintf(err, err_len, "\"%s\": Different lengths for the veteran "
1991 "settings in section '%s'", secfile_name(file),
1992 path);
1993 } else if (count_name == 0) {
1994 /* Nothing defined. */
1995 *vsystem = NULL;
1996 } else {
1997 /* Generate the veteran system. */
1999
2000#define rs_sanity_veteran(_path, _entry, _i, _condition, _action) \
2001 if (_condition) { \
2002 log_error("Invalid veteran definition '%s.%s[%d]'!", \
2003 _path, _entry, _i); \
2004 log_debug("Failed check: '%s'. Update value: '%s'.", \
2005 #_condition, #_action); \
2006 _action; \
2007 }
2008 for (i = 0; i < count_name; i++) {
2009 /* Some sanity checks. */
2010 rs_sanity_veteran(path, "veteran_power_fact", i,
2011 (vlist_power[i] < 0), vlist_power[i] = 0);
2012 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2013 (vlist_raise[i] < 0), vlist_raise[i] = 0);
2014 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2015 (vlist_wraise[i] < 0), vlist_wraise[i] = 0);
2016 rs_sanity_veteran(path, "veteran_move_bonus", i,
2017 (vlist_move[i] < 0), vlist_move[i] = 0);
2018 if (i == 0) {
2019 /* First element.*/
2020 rs_sanity_veteran(path, "veteran_power_fact", i,
2021 (vlist_power[i] != 100), vlist_power[i] = 100);
2022 } else if (i == count_name - 1) {
2023 /* Last element. */
2024 rs_sanity_veteran(path, "veteran_power_fact", i,
2025 (vlist_power[i] < vlist_power[i - 1]),
2026 vlist_power[i] = vlist_power[i - 1]);
2027 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2028 (vlist_raise[i] != 0), vlist_raise[i] = 0);
2029 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2030 (vlist_wraise[i] != 0), vlist_wraise[i] = 0);
2031 } else {
2032 /* All elements in between. */
2033 rs_sanity_veteran(path, "veteran_power_fact", i,
2034 (vlist_power[i] < vlist_power[i - 1]),
2035 vlist_power[i] = vlist_power[i - 1]);
2036 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2037 (vlist_raise[i] > 100), vlist_raise[i] = 100);
2038 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2039 (vlist_wraise[i] > 100), vlist_wraise[i] = 100);
2040 }
2041
2044 vlist_wraise[i]);
2045 }
2046#undef rs_sanity_veteran
2047 }
2048
2049 if (vlist_name) {
2051 }
2052 if (vlist_power) {
2054 }
2055 if (vlist_raise) {
2057 }
2058 if (vlist_wraise) {
2060 }
2061 if (vlist_move) {
2063 }
2064
2065 return ret;
2066}
2067
2068/**********************************************************************/
2071static bool load_ruleset_units(struct section_file *file,
2072 struct rscompat_info *compat)
2073{
2074 int j, ival;
2075 size_t nval;
2076 struct section_list *sec, *csec;
2077 const char *sval, **slist;
2078 const char *filename = secfile_name(file);
2079 char msg[MAX_LEN_MSG];
2080 bool ok = TRUE;
2081
2082 if (!load_ruleset_veteran(file, "veteran_system", &game.veteran, msg,
2083 sizeof(msg))
2084 || game.veteran == NULL) {
2086 "Error loading the default veteran system: %s",
2087 msg);
2088 ok = FALSE;
2089 }
2090
2092 nval = (NULL != sec ? section_list_size(sec) : 0);
2093
2095 nval = (NULL != csec ? section_list_size(csec) : 0);
2096
2097 if (ok) {
2099 int i = uclass_index(uc);
2100 const char *sec_name = section_name(section_list_get(csec, i));
2101
2102 if (secfile_lookup_int(file, &uc->min_speed, "%s.min_speed", sec_name)) {
2103 uc->min_speed *= SINGLE_MOVE;
2104 } else {
2106 ok = FALSE;
2107 break;
2108 }
2109 if (!secfile_lookup_int(file, &uc->hp_loss_pct,
2110 "%s.hp_loss_pct", sec_name)) {
2112 ok = FALSE;
2113 break;
2114 }
2115
2116 uc->non_native_def_pct = secfile_lookup_int_default(file, 100,
2117 "%s.non_native_def_pct",
2118 sec_name);
2119
2120 BV_CLR_ALL(uc->flags);
2121 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
2122 for (j = 0; j < nval; j++) {
2123 sval = slist[j];
2124 if (strcmp(sval, "") == 0) {
2125 continue;
2126 }
2127
2128 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
2130 }
2131
2134 ok = FALSE;
2138 "\"%s\" unit_class \"%s\": unit_type flag \"%s\"!",
2139 filename, uclass_rule_name(uc), sval);
2140 } else {
2142 "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
2143 filename, uclass_rule_name(uc), sval);
2144 }
2145 break;
2146 } else {
2147 BV_SET(uc->flags, ival);
2148 }
2149 }
2150 free(slist);
2151
2152 uc->helptext = lookup_strvec(file, sec_name, "helptext");
2153
2154 if (!ok) {
2155 break;
2156 }
2158 }
2159
2160 if (ok) {
2161 /* Tech and Gov requirements; per unit veteran system */
2163 const int i = utype_index(u);
2164 const struct section *psection = section_list_get(sec, i);
2165 const char *sec_name = section_name(psection);
2166 struct requirement_vector *reqs;
2167
2168 reqs = lookup_req_list(file, compat, sec_name, "reqs",
2169 utype_rule_name(u));
2170
2171 if (reqs == NULL) {
2172 ok = FALSE;
2173 break;
2174 }
2175
2176 requirement_vector_copy(&u->build_reqs, reqs);
2177
2178 if (!load_ruleset_veteran(file, sec_name, &u->veteran,
2179 msg, sizeof(msg))) {
2181 "Error loading the veteran system: %s",
2182 msg);
2183 ok = FALSE;
2184 break;
2185 }
2186
2187 if (!lookup_unit_type(file, sec_name, "obsolete_by",
2188 &u->obsoleted_by, filename,
2189 rule_name_get(&u->name))
2190 || !lookup_unit_type(file, sec_name, "convert_to",
2191 &u->converted_to, filename,
2192 rule_name_get(&u->name))) {
2193 ok = FALSE;
2194 break;
2195 }
2196 u->convert_time = 1; /* default */
2197 lookup_time(file, &u->convert_time, sec_name, "convert_time",
2198 filename, rule_name_get(&u->name), &ok);
2200 }
2201
2202 if (ok) {
2203 /* main stats: */
2205 const int i = utype_index(u);
2206 struct unit_class *pclass;
2207 const char *sec_name = section_name(section_list_get(sec, i));
2208 const char *str;
2209
2210 sval = secfile_lookup_str(file, "%s.class", sec_name);
2212 if (!pclass) {
2214 "\"%s\" unit_type \"%s\": bad class \"%s\".",
2215 filename, utype_rule_name(u), sval);
2216 ok = FALSE;
2217 break;
2218 }
2219 u->uclass = pclass;
2220
2221 sz_strlcpy(u->sound_move,
2222 secfile_lookup_str_default(file, "-", "%s.sound_move",
2223 sec_name));
2224 sz_strlcpy(u->sound_move_alt,
2225 secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
2226 sec_name));
2227 sz_strlcpy(u->sound_fight,
2228 secfile_lookup_str_default(file, "-", "%s.sound_fight",
2229 sec_name));
2230 sz_strlcpy(u->sound_fight_alt,
2231 secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
2232 sec_name));
2233
2234 if ((str = secfile_lookup_str(file, "%s.graphic", sec_name))) {
2235 sz_strlcpy(u->graphic_str, str);
2236 } else {
2238 ok = FALSE;
2239 break;
2240 }
2241 sz_strlcpy(u->graphic_alt,
2242 secfile_lookup_str_default(file, "-", "%s.graphic_alt",
2243 sec_name));
2244 sz_strlcpy(u->graphic_alt2,
2245 secfile_lookup_str_default(file, "-", "%s.graphic_alt2",
2246 sec_name));
2247
2248 if (!secfile_lookup_int(file, &u->build_cost,
2249 "%s.build_cost", sec_name)
2250 || !secfile_lookup_int(file, &u->pop_cost,
2251 "%s.pop_cost", sec_name)
2252 || !secfile_lookup_int(file, &u->attack_strength,
2253 "%s.attack", sec_name)
2254 || !secfile_lookup_int(file, &u->defense_strength,
2255 "%s.defense", sec_name)
2256 || !secfile_lookup_int(file, &u->move_rate,
2257 "%s.move_rate", sec_name)
2258 || !secfile_lookup_int(file, &u->vision_radius_sq,
2259 "%s.vision_radius_sq", sec_name)
2260 || !secfile_lookup_int(file, &u->transport_capacity,
2261 "%s.transport_cap", sec_name)
2262 || !secfile_lookup_int(file, &u->firepower,
2263 "%s.firepower", sec_name)
2264 || !secfile_lookup_int(file, &u->fuel,
2265 "%s.fuel", sec_name)
2266 || !secfile_lookup_int(file, &u->happy_cost,
2267 "%s.uk_happy", sec_name)) {
2269 ok = FALSE;
2270 break;
2271 }
2272 u->hp
2275 RS_MIN_HP,
2276 RS_MAX_HP,
2277 "%s.hitpoints", sec_name);
2278
2279 u->move_rate *= SINGLE_MOVE;
2280
2281 if (u->firepower <= 0) {
2283 "\"%s\" unit_type \"%s\":"
2284 " firepower is %d,"
2285 " but must be at least 1. "
2286 " If you want no attack ability,"
2287 " set the unit's attack strength to 0.",
2288 filename, utype_rule_name(u), u->firepower);
2289 ok = FALSE;
2290 break;
2291 }
2292
2293 lookup_cbonus_list(u->bonuses, file, sec_name, "bonuses");
2294
2296 u->upkeep[o] = secfile_lookup_int_default(file, 0, "%s.uk_%s",
2297 sec_name,
2300
2301 slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec_name);
2302
2303 BV_CLR_ALL(u->cargo);
2304 for (j = 0; j < nval; j++) {
2305 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2306
2307 if (!uclass) {
2309 "\"%s\" unit_type \"%s\":"
2310 "has unknown unit class %s as cargo.",
2311 filename, utype_rule_name(u), slist[j]);
2312 ok = FALSE;
2313 break;
2314 }
2315
2316 BV_SET(u->cargo, uclass_index(uclass));
2317 }
2318 free(slist);
2319
2320 if (!ok) {
2321 break;
2322 }
2323
2324 slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec_name);
2325 BV_CLR_ALL(u->targets);
2326 for (j = 0; j < nval; j++) {
2327 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2328
2329 if (!uclass) {
2331 "\"%s\" unit_type \"%s\":"
2332 "has unknown unit class %s as target.",
2333 filename, utype_rule_name(u), slist[j]);
2334 ok = FALSE;
2335 break;
2336 }
2337
2338 BV_SET(u->targets, uclass_index(uclass));
2339 }
2340 free(slist);
2341
2342 if (!ok) {
2343 break;
2344 }
2345
2346 slist = secfile_lookup_str_vec(file, &nval, "%s.embarks", sec_name);
2347 BV_CLR_ALL(u->embarks);
2348 for (j = 0; j < nval; j++) {
2349 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2350
2351 if (!uclass) {
2353 "\"%s\" unit_type \"%s\":"
2354 "has unknown unit class %s as embarkable.",
2355 filename, utype_rule_name(u), slist[j]);
2356 ok = FALSE;
2357 break;
2358 }
2359
2360 BV_SET(u->embarks, uclass_index(uclass));
2361 }
2362 free(slist);
2363
2364 if (!ok) {
2365 break;
2366 }
2367
2368 slist = secfile_lookup_str_vec(file, &nval, "%s.disembarks", sec_name);
2369 BV_CLR_ALL(u->disembarks);
2370 for (j = 0; j < nval; j++) {
2371 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2372
2373 if (!uclass) {
2375 "\"%s\" unit_type \"%s\":"
2376 "has unknown unit class %s as disembarkable.",
2377 filename, utype_rule_name(u), slist[j]);
2378 ok = FALSE;
2379 break;
2380 }
2381
2382 BV_SET(u->disembarks, uclass_index(uclass));
2383 }
2384 free(slist);
2385
2386 if (!ok) {
2387 break;
2388 }
2389
2390 /* Set also all classes that are never unreachable as targets,
2391 * embarks, and disembarks. */
2394 BV_SET(u->targets, uclass_index(preachable));
2395 BV_SET(u->embarks, uclass_index(preachable));
2396 BV_SET(u->disembarks, uclass_index(preachable));
2397 }
2399
2400 str = secfile_lookup_str_default(file, "Main", "%s.vision_layer",
2401 sec_name);
2403 if (!vision_layer_is_valid(u->vlayer)) {
2405 "\"%s\" unit_type \"%s\":"
2406 "has unknown vision layer %s.",
2407 filename, utype_rule_name(u), str);
2408 ok = FALSE;
2409 break;
2410 }
2411
2412 u->helptext = lookup_strvec(file, sec_name, "helptext");
2413
2414 u->paratroopers_range = secfile_lookup_int_default(file,
2415 0, "%s.paratroopers_range", sec_name);
2416
2417 u->bombard_rate = secfile_lookup_int_default(file, 0,
2418 "%s.bombard_rate", sec_name);
2419 u->city_slots = secfile_lookup_int_default(file, 0,
2420 "%s.city_slots", sec_name);
2421 u->city_size = secfile_lookup_int_default(file, 1,
2422 "%s.city_size", sec_name);
2423
2425 "%s.tp_defense", sec_name);
2426 u->tp_defense = transp_def_type_by_name(sval, fc_strcasecmp);
2427 if (!transp_def_type_is_valid(u->tp_defense)) {
2429 "\"%s\" unit_type \"%s\":"
2430 " bad tp_defense \"%s\".",
2431 filename, utype_rule_name(u), sval);
2432 ok = FALSE;
2433 break;
2434 }
2436 }
2437
2438 if (ok) {
2439 /* Flags */
2441 const int i = utype_index(u);
2442
2443 BV_CLR_ALL(u->flags);
2445
2446 slist = secfile_lookup_str_vec(file, &nval, "%s.flags",
2448 for (j = 0; j < nval; j++) {
2449 sval = slist[j];
2450 if (0 == strcmp(sval, "")) {
2451 continue;
2452 }
2455 ok = FALSE;
2459 "\"%s\" unit_type \"%s\": unit_class flag!",
2460 filename, utype_rule_name(u));
2461 } else {
2463 "\"%s\" unit_type \"%s\": bad flag name \"%s\".",
2464 filename, utype_rule_name(u), sval);
2465 }
2466 break;
2467 } else {
2468 BV_SET(u->flags, ival);
2469 }
2470 }
2471 free(slist);
2472
2473 if (!ok) {
2474 break;
2475 }
2477 }
2478
2479 /* Roles */
2480 if (ok) {
2482 const int i = utype_index(u);
2483
2484 BV_CLR_ALL(u->roles);
2485
2486 slist = secfile_lookup_str_vec(file, &nval, "%s.roles",
2488 for (j = 0; j < nval; j++) {
2489 sval = slist[j];
2490 if (strcmp(sval, "") == 0) {
2491 continue;
2492 }
2496 "\"%s\" unit_type \"%s\": bad role name \"%s\".",
2497 filename, utype_rule_name(u), sval);
2498 ok = FALSE;
2499 break;
2500 } else {
2501 BV_SET(u->roles, ival - L_FIRST);
2502 }
2504 }
2505 free(slist);
2507 }
2508
2509 if (ok) {
2510 /* Some more consistency checking: */
2513 if (!valid_advance(padv)) {
2515 "\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
2516 filename, utype_rule_name(u),
2518 ok = FALSE;
2519 break;
2520 }
2522
2523 if (!ok) {
2524 break;
2525 }
2527 }
2528
2531
2532 if (ok) {
2534 }
2535
2536 return ok;
2537}
2538
2539/**********************************************************************/
2543static bool load_building_names(struct section_file *file,
2544 struct rscompat_info *compat)
2545{
2546 struct section_list *sec;
2547 int i, nval = 0;
2548 const char *filename = secfile_name(file);
2549 bool ok = TRUE;
2550 const char *flag;
2551
2552 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2553 return FALSE;
2554 }
2555
2556 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2557 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2558
2559 /* The names: */
2561 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2563 "\"%s\": No improvements?!?", filename);
2564 ok = FALSE;
2565 } else {
2566 log_verbose("%d improvement types (including possibly unused)", nval);
2567 if (nval > B_LAST) {
2569 "\"%s\": Too many improvements (%d, max %d)",
2570 filename, nval, B_LAST);
2571 ok = FALSE;
2572 }
2573 }
2574
2575 if (ok) {
2577
2578 for (i = 0; i < nval; i++) {
2579 struct impr_type *b = improvement_by_number(i);
2580
2581 if (!ruleset_load_names(&b->name, NULL, file, section_name(section_list_get(sec, i)))) {
2582 ok = FALSE;
2583 break;
2584 }
2585 }
2586 }
2587
2588 /* User building flag names */
2589 for (i = 0;
2590 (flag = secfile_lookup_str_default(file, NULL,
2591 "control.building_flags%d.name",
2592 i));
2593 i++) {
2594 const char *helptxt = secfile_lookup_str_default(file, NULL,
2595 "control.building_flags%d.helptxt", i);
2596
2598 != impr_flag_id_invalid()) {
2600 "\"%s\": Duplicate building flag name '%s'",
2601 filename, flag);
2602 ok = FALSE;
2603 break;
2604 }
2607 "\"%s\": Too many user building flags!",
2608 filename);
2609 ok = FALSE;
2610 break;
2611 }
2612
2613 set_user_impr_flag_name(IF_USER_FLAG_1 + i, flag, helptxt);
2614 }
2615
2617
2618 return ok;
2619}
2620
2621/**********************************************************************/
2624static bool load_ruleset_buildings(struct section_file *file,
2625 struct rscompat_info *compat)
2626{
2627 struct section_list *sec;
2628 const char *item;
2629 int i, nval;
2630 const char *filename = secfile_name(file);
2631 bool ok = TRUE;
2632
2634 nval = (NULL != sec ? section_list_size(sec) : 0);
2635
2636 for (i = 0; i < nval && ok; i++) {
2637 struct impr_type *b = improvement_by_number(i);
2638 const char *sec_name = section_name(section_list_get(sec, i));
2639 struct requirement_vector *reqs =
2640 lookup_req_list(file, compat, sec_name, "reqs",
2642
2643 if (reqs == NULL) {
2644 ok = FALSE;
2645 break;
2646 } else {
2647 const char *sval, **slist;
2648 int j, ival;
2649 size_t nflags;
2650
2651 item = secfile_lookup_str(file, "%s.genus", sec_name);
2653 if (!impr_genus_id_is_valid(b->genus)) {
2655 "\"%s\" improvement \"%s\": couldn't match "
2656 "genus \"%s\".", filename,
2658 ok = FALSE;
2659 break;
2660 }
2661
2662 slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec_name);
2663 BV_CLR_ALL(b->flags);
2664
2665 for (j = 0; j < nflags; j++) {
2666 sval = slist[j];
2667 if (strcmp(sval, "") == 0) {
2668 continue;
2669 }
2673 "\"%s\" improvement \"%s\": bad flag name \"%s\".",
2674 filename, improvement_rule_name(b), sval);
2675 ok = FALSE;
2676 break;
2677 } else {
2678 BV_SET(b->flags, ival);
2679 }
2680 }
2681 free(slist);
2682
2683 if (!ok) {
2684 break;
2685 }
2686
2688
2689 {
2690 struct requirement_vector *obs_reqs =
2691 lookup_req_list(file, compat, sec_name, "obsolete_by",
2693
2694 if (obs_reqs == NULL) {
2695 ok = FALSE;
2696 break;
2697 } else {
2698 requirement_vector_copy(&b->obsolete_by, obs_reqs);
2699 }
2700 }
2701
2702 if (!secfile_lookup_int(file, &b->build_cost,
2703 "%s.build_cost", sec_name)
2704 || !secfile_lookup_int(file, &b->upkeep,
2705 "%s.upkeep", sec_name)
2706 || !secfile_lookup_int(file, &b->sabotage,
2707 "%s.sabotage", sec_name)) {
2709 ok = FALSE;
2710 break;
2711 }
2712
2715 "%s.graphic", sec_name));
2718 "%s.graphic_alt", sec_name));
2721 "%s.graphic_alt2", sec_name));
2722
2725 "%s.sound", sec_name));
2728 "%s.sound_alt", sec_name));
2731 "%s.sound_alt2", sec_name));
2732 b->helptext = lookup_strvec(file, sec_name, "helptext");
2733 }
2734 }
2735
2737 if (ok) {
2739 }
2740
2741 return ok;
2742}
2743
2744/**********************************************************************/
2748static bool load_terrain_names(struct section_file *file,
2749 struct rscompat_info *compat)
2750{
2751 int nval = 0;
2752 struct section_list *sec = NULL;
2753 const char *flag;
2754 int i;
2755 const char *filename = secfile_name(file);
2756 bool ok = TRUE;
2757
2758 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2759 return FALSE;
2760 }
2761
2762 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2763 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2764
2765 /* User terrain flag names */
2766 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
2767 i++) {
2768 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
2769 i);
2770
2774 "\"%s\": Duplicate terrain flag name '%s'",
2775 filename, flag);
2776 ok = FALSE;
2777 break;
2778 }
2779 if (i > MAX_NUM_USER_TER_FLAGS) {
2781 "\"%s\": Too many user terrain flags!",
2782 filename);
2783 ok = FALSE;
2784 break;
2785 }
2786
2787 set_user_terrain_flag_name(TER_USER_1 + i, flag, helptxt);
2788 }
2789
2790 if (ok) {
2791 /* Blank the remaining terrain user flag slots. */
2792 for (; i < MAX_NUM_USER_TER_FLAGS; i++) {
2794 }
2795 }
2796
2797 /* User extra flag names */
2798 for (i = 0;
2799 (flag = secfile_lookup_str_default(file, NULL,
2800 "control.extra_flags%d.name",
2801 i));
2802 i++) {
2803 const char *helptxt = secfile_lookup_str_default(file, NULL,
2804 "control.extra_flags%d.helptxt", i);
2805
2807 != extra_flag_id_invalid()) {
2809 "\"%s\": Duplicate extra flag name '%s'",
2810 filename, flag);
2811 ok = FALSE;
2812 break;
2813 }
2816 "\"%s\": Too many user extra flags!",
2817 filename);
2818 ok = FALSE;
2819 break;
2820 }
2821
2822 set_user_extra_flag_name(EF_USER_FLAG_1 + i, flag, helptxt);
2823 }
2824
2825 if (ok) {
2826 /* Blank the remaining extra user flag slots. */
2827 for (; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
2829 }
2830
2831 /* Terrain names */
2832
2834 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2836 "\"%s\": ruleset doesn't have any terrains.",
2837 filename);
2838 ok = FALSE;
2839 } else {
2840 if (nval > MAX_NUM_TERRAINS) {
2842 "\"%s\": Too many terrains (%d, max %d)",
2843 filename, nval, MAX_NUM_TERRAINS);
2844 ok = FALSE;
2845 }
2846 }
2847 }
2848
2849 if (ok) {
2851
2852 /* avoid re-reading files */
2853 if (terrain_sections) {
2855 }
2857
2858 terrain_type_iterate(pterrain) {
2859 const int terri = terrain_index(pterrain);
2860 const char *sec_name = section_name(section_list_get(sec, terri));
2861
2862 if (!ruleset_load_names(&pterrain->name, NULL, file, sec_name)) {
2863 ok = FALSE;
2864 break;
2865 }
2866
2869 }
2870
2872 sec = NULL;
2873
2874 /* extra names */
2875
2876 if (ok) {
2878 nval = (NULL != sec ? section_list_size(sec) : 0);
2879 if (nval > MAX_EXTRA_TYPES) {
2881 "\"%s\": Too many extra types (%d, max %d)",
2882 filename, nval, MAX_EXTRA_TYPES);
2883 ok = FALSE;
2884 }
2885 }
2886
2887 if (ok) {
2888 int idx;
2889
2891
2892 if (extra_sections) {
2894 }
2896
2897 if (ok) {
2898 for (idx = 0; idx < nval; idx++) {
2899 const char *sec_name = section_name(section_list_get(sec, idx));
2900 struct extra_type *pextra = extra_by_number(idx);
2901
2902 if (!ruleset_load_names(&pextra->name, NULL, file, sec_name)) {
2903 ok = FALSE;
2904 break;
2905 }
2907 }
2908 }
2909 }
2910
2912 sec = NULL;
2913
2914 /* Base names */
2915
2916 if (ok) {
2918 nval = (NULL != sec ? section_list_size(sec) : 0);
2919 if (nval > MAX_EXTRA_TYPES) {
2921 "\"%s\": Too many base types (%d, max %d)",
2922 filename, nval, MAX_EXTRA_TYPES);
2923 ok = FALSE;
2924 }
2925
2927 }
2928
2929 if (ok) {
2930 int idx;
2931
2932 if (base_sections) {
2934 }
2936
2937 /* Cannot use base_type_iterate() before bases are added to
2938 * EC_BASE caused_by list. Have to get them by extra_type_by_rule_name() */
2939 for (idx = 0; idx < nval; idx++) {
2940 const char *sec_name = section_name(section_list_get(sec, idx));
2941 const char *base_name = secfile_lookup_str(file, "%s.extra", sec_name);
2942
2943 if (base_name != NULL) {
2945
2946 if (pextra != NULL) {
2947 base_type_init(pextra, idx);
2949 } else {
2951 "No extra definition matching base definition \"%s\"",
2952 base_name);
2953 ok = FALSE;
2954 }
2955 } else {
2957 "Base section \"%s\" does not associate base with any extra",
2958 sec_name);
2959 ok = FALSE;
2960 }
2961 }
2962 }
2963
2965 sec = NULL;
2966
2967 /* Road names */
2968
2969 if (ok) {
2971 nval = (NULL != sec ? section_list_size(sec) : 0);
2972 if (nval > MAX_EXTRA_TYPES) {
2974 "\"%s\": Too many road types (%d, max %d)",
2975 filename, nval, MAX_EXTRA_TYPES);
2976 ok = FALSE;
2977 }
2978
2980 }
2981
2982 if (ok) {
2983 int idx;
2984
2985 if (road_sections) {
2987 }
2989
2990 /* Cannot use extra_type_by_cause_iterate(EC_ROAD) before roads are added to
2991 * EC_ROAD caused_by list. Have to get them by extra_type_by_rule_name() */
2992 for (idx = 0; idx < nval; idx++) {
2993 const char *sec_name = section_name(section_list_get(sec, idx));
2994 const char *road_name = secfile_lookup_str(file, "%s.extra", sec_name);
2995
2996 if (road_name != NULL) {
2998
2999 if (pextra != NULL) {
3000 road_type_init(pextra, idx);
3002 } else {
3004 "No extra definition matching road definition \"%s\"",
3005 road_name);
3006 ok = FALSE;
3007 }
3008 } else {
3010 "Road section \"%s\" does not associate road with any extra",
3011 sec_name);
3012 ok = FALSE;
3013 }
3014 }
3015 }
3016
3018 sec = NULL;
3019
3020 /* Resource names */
3021 if (ok) {
3023 nval = (NULL != sec ? section_list_size(sec) : 0);
3024 if (nval > MAX_EXTRA_TYPES) {
3026 "\"%s\": Too many resource types (%d, max %d)",
3027 filename, nval, MAX_EXTRA_TYPES);
3028 ok = FALSE;
3029 }
3030
3032 }
3033
3034 if (ok) {
3035 int idx;
3036
3037 if (resource_sections) {
3039 }
3041
3042 /* Cannot use resource_type_iterate() before resource are added to
3043 * EC_RESOURCE caused_by list. Have to get them by extra_type_by_rule_name() */
3044 for (idx = 0; idx < nval; idx++) {
3045 const char *sec_name = section_name(section_list_get(sec, idx));
3046 const char *resource_name;
3047 struct extra_type *pextra = NULL;
3048
3050
3051 if (resource_name != NULL) {
3053
3054 if (pextra != NULL) {
3055 resource_type_init(pextra);
3057 } else {
3059 "No extra definition matching resource definition \"%s\"",
3061 ok = FALSE;
3062 }
3063 } else {
3065 "Resource section %s does not list extra this resource belongs to.",
3066 sec_name);
3067 ok = FALSE;
3068 }
3069 }
3070 }
3071
3073
3074 return ok;
3075}
3076
3077/**********************************************************************/
3080static bool load_ruleset_terrain(struct section_file *file,
3081 struct rscompat_info *compat)
3082{
3083 size_t nval, nval2;
3084 int j;
3085 bool compat_road = FALSE;
3086 bool compat_rail = FALSE;
3087 bool compat_river = FALSE;
3088 const char **res;
3089 const char *filename = secfile_name(file);
3090 const char *text;
3091 int *res_freq;
3092 bool ok = TRUE;
3093
3094 /* parameters */
3095
3096 terrain_control.ocean_reclaim_requirement_pct
3097 = secfile_lookup_int_default(file, 101,
3098 "parameters.ocean_reclaim_requirement");
3099 terrain_control.land_channel_requirement_pct
3100 = secfile_lookup_int_default(file, 101,
3101 "parameters.land_channel_requirement");
3102 terrain_control.terrain_thaw_requirement_pct
3103 = secfile_lookup_int_default(file, 101,
3104 "parameters.thaw_requirement");
3105 terrain_control.terrain_freeze_requirement_pct
3106 = secfile_lookup_int_default(file, 101,
3107 "parameters.freeze_requirement");
3108 terrain_control.lake_max_size
3110 "parameters.lake_max_size");
3111 terrain_control.min_start_native_area
3113 "parameters.min_start_native_area");
3114 terrain_control.move_fragments
3116 "parameters.move_fragments");
3117 if (terrain_control.move_fragments < 1) {
3119 "\"%s\": move_fragments must be at least 1",
3120 filename);
3121 ok = FALSE;
3122 }
3124 terrain_control.igter_cost
3126 "parameters.igter_cost");
3127 if (terrain_control.igter_cost < 1) {
3129 "\"%s\": igter_cost must be at least 1",
3130 filename);
3131 ok = FALSE;
3132 }
3133 terrain_control.infrapoints = FALSE; /* This will be updated if we find
3134 * an placeable extra. */
3135
3136 terrain_control.pythagorean_diagonal
3138 "parameters.pythagorean_diagonal");
3139
3142 "parameters.ocean_resources");
3143
3144 text = secfile_lookup_str_default(file,
3145 N_("?gui_type:Build Type A Base"),
3146 "extraui.ui_name_base_fortress");
3147 sz_strlcpy(terrain_control.gui_type_base0, text);
3148
3149 text = secfile_lookup_str_default(file,
3150 N_("?gui_type:Build Type B Base"),
3151 "extraui.ui_name_base_airbase");
3152 sz_strlcpy(terrain_control.gui_type_base1, text);
3153
3154 if (ok) {
3155 /* Terrain details */
3156
3157 terrain_type_iterate(pterrain) {
3158 const char **slist;
3159 const int i = terrain_index(pterrain);
3160 const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
3161 const char *cstr;
3162 const char *ename;
3163
3164 sz_strlcpy(pterrain->graphic_str,
3165 secfile_lookup_str(file, "%s.graphic", tsection));
3166 sz_strlcpy(pterrain->graphic_alt,
3168 "%s.graphic_alt", tsection));
3169 sz_strlcpy(pterrain->graphic_alt2,
3171 "%s.graphic_alt2", tsection));
3172
3173 pterrain->identifier
3174 = secfile_lookup_str(file, "%s.identifier", tsection)[0];
3175 if ('\0' == pterrain->identifier) {
3177 "\"%s\" [%s] identifier missing value.",
3178 filename, tsection);
3179 ok = FALSE;
3180 break;
3181 }
3182 if (TERRAIN_UNKNOWN_IDENTIFIER == pterrain->identifier) {
3184 "\"%s\" [%s] cannot use '%c' as an identifier;"
3185 " it is reserved for unknown terrain.",
3186 filename, tsection, pterrain->identifier);
3187 ok = FALSE;
3188 break;
3189 }
3190 for (j = T_FIRST; j < i; j++) {
3191 if (pterrain->identifier == terrain_by_number(j)->identifier) {
3193 "\"%s\" [%s] has the same identifier as [%s].",
3194 filename, tsection,
3196 ok = FALSE;
3197 break;
3198 }
3199 }
3200
3201 if (!ok) {
3202 break;
3203 }
3204
3205 cstr = secfile_lookup_str(file, "%s.class", tsection);
3206 pterrain->tclass = terrain_class_by_name(cstr, fc_strcasecmp);
3207 if (!terrain_class_is_valid(pterrain->tclass)) {
3209 "\"%s\": [%s] unknown class \"%s\"",
3210 filename, tsection, cstr);
3211 ok = FALSE;
3212 break;
3213 }
3214
3215 if (!secfile_lookup_int(file, &pterrain->movement_cost,
3216 "%s.movement_cost", tsection)
3217 || !secfile_lookup_int(file, &pterrain->defense_bonus,
3218 "%s.defense_bonus", tsection)) {
3220 ok = FALSE;
3221 break;
3222 }
3223
3225 pterrain->output[o]
3226 = secfile_lookup_int_default(file, 0, "%s.%s", tsection,
3229
3230 res = secfile_lookup_str_vec(file, &nval, "%s.resources", tsection);
3232 "%s.resource_freq", tsection);
3233 if (nval2 > 0 && nval2 != nval) {
3235 "\"%s\": [%s] Different lengths for resources "
3236 "and resource frequencies",
3237 filename, tsection);
3238 ok = FALSE;
3239 }
3240 pterrain->resources = fc_calloc(nval + 1, sizeof(*pterrain->resources));
3241 pterrain->resource_freq = fc_calloc(nval + 1,
3242 sizeof(*pterrain->resource_freq));
3243 for (j = 0; j < nval; j++) {
3244 pterrain->resources[j] = lookup_resource(filename, res[j], tsection);
3245 if (pterrain->resources[j] == NULL) {
3246 ok = FALSE;
3247 break;
3248 }
3249 pterrain->resource_freq[j] = j < nval2
3250 ? res_freq[j]
3252 if (pterrain->resource_freq[j] < RESOURCE_FREQUENCY_MINIMUM
3253 || pterrain->resource_freq[j] > RESOURCE_FREQUENCY_MAXIMUM) {
3255 "\"%s\": [%s] Resource frequency '%d' "
3256 "outside allowed range",
3257 filename, tsection,
3258 pterrain->resource_freq[j]);
3259 ok = FALSE;
3260 break;
3261 }
3262 }
3263 pterrain->resources[nval] = NULL;
3264 /* Terminating zero technically not necessary */
3265 pterrain->resource_freq[nval] = 0;
3266 free(res);
3267 res = NULL;
3268 free(res_freq);
3269 res_freq = NULL;
3270
3271 if (!ok) {
3272 break;
3273 }
3274
3276 pterrain->road_output_incr_pct[o]
3277 = secfile_lookup_int_default(file, 0, "%s.road_%s_incr_pct",
3280
3281 if (!lookup_time(file, &pterrain->base_time, tsection, "base_time",
3282 filename, NULL, &ok)
3283 || !lookup_time(file, &pterrain->road_time, tsection, "road_time",
3284 filename, NULL, &ok)) {
3286 ok = FALSE;
3287 break;
3288 }
3289
3290 if (!lookup_terrain(file, "cultivate_result", filename, pterrain,
3291 &pterrain->cultivate_result, FALSE)) {
3292 ruleset_error(NULL, LOG_ERROR, "%s: No cultivate_result", tsection);
3293 ok = FALSE;
3294 break;
3295 }
3296 if (pterrain->cultivate_result == pterrain) {
3298 "%s: Cultivating result in terrain itself.",
3299 tsection);
3300 ok = FALSE;
3301 break;
3302 }
3303 if (!secfile_lookup_int(file, &pterrain->irrigation_food_incr,
3304 "%s.irrigation_food_incr", tsection)
3305 || !lookup_time(file, &pterrain->irrigation_time,
3306 tsection, "irrigation_time", filename, NULL, &ok)) {
3308 ok = FALSE;
3309 break;
3310 }
3311
3312 if (!lookup_terrain(file, "plant_result", filename, pterrain,
3313 &pterrain->plant_result, FALSE)) {
3314 ruleset_error(NULL, LOG_ERROR, "%s: No plant_result", tsection);
3315 ok = FALSE;
3316 break;
3317 }
3318 if (pterrain->plant_result == pterrain) {
3320 "%s: Planting result in terrain itself.",
3321 tsection);
3322 ok = FALSE;
3323 break;
3324 }
3325 if (!secfile_lookup_int(file, &pterrain->mining_shield_incr,
3326 "%s.mining_shield_incr", tsection)
3327 || !lookup_time(file, &pterrain->mining_time,
3328 tsection, "mining_time", filename, NULL, &ok)) {
3330 ok = FALSE;
3331 break;
3332 }
3333
3334 if (!lookup_time(file, &pterrain->cultivate_time,
3335 tsection, "cultivate_time", filename, NULL, &ok)) {
3337 "%s: Missing cultivate_time", tsection);
3338 ok = FALSE;
3339 break;
3340 }
3341 if ((pterrain->cultivate_result != NULL
3342 && pterrain->cultivate_time <= 0)
3343 || (pterrain->cultivate_result == NULL
3344 && pterrain->cultivate_time > 0)) {
3346 "%s: cultivate_result and cultivate_time disagree "
3347 "whether cultivating is enabled", tsection);
3348 ok = FALSE;
3349 break;
3350 }
3351
3352 if (!lookup_time(file, &pterrain->plant_time,
3353 tsection, "plant_time", filename, NULL, &ok)) {
3355 "%s: Missing plant_time", tsection);
3356 ok = FALSE;
3357 break;
3358 }
3359 if ((pterrain->plant_result != NULL
3360 && pterrain->plant_time <= 0)
3361 || (pterrain->plant_result == NULL
3362 && pterrain->plant_time > 0)) {
3364 "%s: plant_result and plant_time disagree "
3365 "whether planting is enabled", tsection);
3366 ok = FALSE;
3367 break;
3368 }
3369
3370 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
3371 pterrain->num_animals = 1;
3372 pterrain->animals = fc_calloc(pterrain->num_animals,
3373 sizeof(*pterrain->animals));
3374 if (!lookup_unit_type(file, tsection, "animal",
3375 &(pterrain->animals[0]), filename,
3376 rule_name_get(&pterrain->name))) {
3377 ok = FALSE;
3378 break;
3379 }
3380 /* if "None", pterrain->animals[0] will be nullptr, so adjust */
3381 if (pterrain->animals[0] == nullptr) {
3382 pterrain->num_animals = 0;
3383 free(pterrain->animals);
3384 pterrain->animals = nullptr;
3385 }
3386 } else {
3387 res = secfile_lookup_str_vec(file, &nval, "%s.animals", tsection);
3388 pterrain->num_animals = nval;
3389 if (pterrain->num_animals == 0) {
3390 pterrain->animals = nullptr;
3391 } else {
3392 pterrain->animals = fc_calloc(pterrain->num_animals,
3393 sizeof(*pterrain->animals));
3394 for (j = 0; j < pterrain->num_animals; j++) {
3395 pterrain->animals[j] = unit_type_by_rule_name(res[j]);
3396 if (pterrain->animals[j] == NULL) {
3397 ok = FALSE;
3398 break;
3399 }
3400 }
3401 }
3402 free(res);
3403 res = NULL;
3404 if (!ok) {
3405 break;
3406 }
3407 }
3408
3409 if (!lookup_terrain(file, "transform_result", filename, pterrain,
3410 &pterrain->transform_result, TRUE)) {
3411 ok = FALSE;
3412 break;
3413 }
3414 if (!lookup_time(file, &pterrain->transform_time,
3415 tsection, "transform_time", filename, NULL, &ok)) {
3417 ok = FALSE;
3418 break;
3419 }
3420 if ((pterrain->transform_result != NULL
3421 && pterrain->transform_time <= 0)
3422 || (pterrain->transform_result == NULL
3423 && pterrain->transform_time > 0)) {
3425 "%s: transform_result and transform_time disagree "
3426 "whether transforming is enabled", tsection);
3427 ok = FALSE;
3428 break;
3429 }
3430
3431 pterrain->placing_time = 1; /* Default */
3432 lookup_time(file, &pterrain->placing_time,
3433 tsection, "placing_time", filename, NULL, &ok);
3434
3435 pterrain->pillage_time = 1; /* Default */
3436 lookup_time(file, &pterrain->pillage_time,
3437 tsection, "pillage_time", filename, NULL, &ok);
3438
3439 if (!lookup_terrain(file, "warmer_wetter_result", filename, pterrain,
3440 &pterrain->warmer_wetter_result, TRUE)
3441 || !lookup_terrain(file, "warmer_drier_result", filename, pterrain,
3442 &pterrain->warmer_drier_result, TRUE)
3443 || !lookup_terrain(file, "cooler_wetter_result", filename, pterrain,
3444 &pterrain->cooler_wetter_result, TRUE)
3445 || !lookup_terrain(file, "cooler_drier_result", filename, pterrain,
3446 &pterrain->cooler_drier_result, TRUE)) {
3447 ok = FALSE;
3448 break;
3449 }
3450
3451 /* Set default removal times */
3452 extra_type_iterate(pextra) {
3453 pterrain->extra_removal_times[extra_index(pextra)] = 0;
3455
3456 for (j = 0; (ename = secfile_lookup_str_default(file, NULL,
3457 "%s.extra_settings%d.extra",
3458 tsection, j)); j++) {
3459 const struct extra_type *pextra = extra_type_by_rule_name(ename);
3460
3461 if (pextra != NULL) {
3462 char time_sections[512];
3463
3465 "%s.extra_settings%d", tsection, j);
3466
3467 lookup_time(file, &pterrain->extra_removal_times[extra_index(pextra)],
3468 time_sections, "removal_time", filename, NULL, &ok);
3469 } else {
3471 "\"%s\" [%s] has settings for unknown extra \"%s\".",
3472 filename, tsection, ename);
3473 ok = FALSE;
3474 break;
3475 }
3476 }
3477
3478 if (ok) {
3479 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsection);
3480 BV_CLR_ALL(pterrain->flags);
3481 for (j = 0; j < nval; j++) {
3482 const char *sval = slist[j];
3483 enum terrain_flag_id flag
3485
3486 if (!terrain_flag_id_is_valid(flag)) {
3488 "\"%s\" [%s] has unknown flag \"%s\".",
3489 filename, tsection, sval);
3490 ok = FALSE;
3491 break;
3492 } else {
3493 BV_SET(pterrain->flags, flag);
3494 }
3495 }
3496
3497 free(slist);
3498 }
3499
3500 if (!ok) {
3501 break;
3502 }
3503
3504 {
3506
3510 pterrain->property[mtp]
3511 = secfile_lookup_int_default(file, 0, "%s.property_%s", tsection,
3513 }
3514 }
3515
3516 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
3517 BV_CLR_ALL(pterrain->native_to);
3518 for (j = 0; j < nval; j++) {
3519 struct unit_class *class = unit_class_by_rule_name(slist[j]);
3520
3521 if (!class) {
3523 "\"%s\" [%s] is native to unknown unit class \"%s\".",
3524 filename, tsection, slist[j]);
3525 ok = FALSE;
3526 break;
3527 } else {
3528 BV_SET(pterrain->native_to, uclass_index(class));
3529 }
3530 }
3531 free(slist);
3532
3533 if (!ok) {
3534 break;
3535 }
3536
3537 /* Get terrain color */
3538 {
3539 fc_assert_ret_val(pterrain->rgb == NULL, FALSE);
3540
3541 if (!rgbcolor_load(file, &pterrain->rgb, "%s.color", tsection)) {
3543 "Missing terrain color definition: %s",
3544 secfile_error());
3545 ok = FALSE;
3546 break;
3547 }
3548 }
3549
3550 pterrain->helptext = lookup_strvec(file, tsection, "helptext");
3552 }
3553
3554 if (ok) {
3555 /* Extra details */
3556 extra_type_iterate(pextra) {
3557 BV_CLR_ALL(pextra->conflicts);
3559
3560 extra_type_iterate(pextra) {
3561 int eidx = extra_index(pextra);
3562 const char *section = &extra_sections[eidx * MAX_SECTION_LABEL];
3563 const char **slist;
3564 struct requirement_vector *reqs;
3565 const char *catname;
3566 int cj;
3567 enum extra_cause cause;
3569 const char *eus_name;
3570 const char *vis_req_name;
3571 const struct advance *vis_req;
3572
3573 catname = secfile_lookup_str(file, "%s.category", section);
3574 if (catname == NULL) {
3576 "\"%s\" extra \"%s\" has no category.",
3577 filename, extra_rule_name(pextra));
3578 ok = FALSE;
3579 break;
3580 }
3581 pextra->category = extra_category_by_name(catname, fc_strcasecmp);
3582 if (!extra_category_is_valid(pextra->category)) {
3584 "\"%s\" extra \"%s\" has invalid category \"%s\".",
3585 filename, extra_rule_name(pextra), catname);
3586 ok = FALSE;
3587 break;
3588 }
3589
3590 slist = secfile_lookup_str_vec(file, &nval, "%s.causes", section);
3591 pextra->causes = 0;
3592 for (cj = 0; cj < nval; cj++) {
3593 const char *sval = slist[cj];
3595
3596 if (!extra_cause_is_valid(cause)) {
3598 "\"%s\" extra \"%s\": unknown cause \"%s\".",
3599 filename, extra_rule_name(pextra), sval);
3600 ok = FALSE;
3601 break;
3602 } else {
3603 pextra->causes |= (1 << cause);
3604 extra_to_caused_by_list(pextra, cause);
3605 }
3606 }
3607
3608 if (pextra->causes == 0) {
3609 /* Extras that do not have any causes added to EC_NONE list */
3611 }
3612
3613 if (!is_extra_caused_by(pextra, EC_BASE)
3614 && !is_extra_caused_by(pextra, EC_ROAD)
3615 && !is_extra_caused_by(pextra, EC_RESOURCE)) {
3616 /* Not a base, road, nor resource, so special */
3617 pextra->data.special_idx = extra_type_list_size(extra_type_list_by_cause(EC_SPECIAL));
3619 }
3620
3621 free(slist);
3622
3623 slist = secfile_lookup_str_vec(file, &nval, "%s.rmcauses", section);
3624 pextra->rmcauses = 0;
3625 for (j = 0; j < nval; j++) {
3626 const char *sval = slist[j];
3627
3629
3632 "\"%s\" extra \"%s\": unknown rmcause \"%s\".",
3633 filename, extra_rule_name(pextra), sval);
3634 ok = FALSE;
3635 break;
3636 } else {
3637 pextra->rmcauses |= (1 << rmcause);
3639 }
3640 }
3641
3642 free(slist);
3643
3644 sz_strlcpy(pextra->activity_gfx,
3646 "%s.activity_gfx", section));
3647 sz_strlcpy(pextra->act_gfx_alt,
3649 "%s.act_gfx_alt", section));
3650 sz_strlcpy(pextra->act_gfx_alt2,
3652 "%s.act_gfx_alt2", section));
3653 sz_strlcpy(pextra->rmact_gfx,
3655 "%s.rmact_gfx", section));
3656 sz_strlcpy(pextra->rmact_gfx_alt,
3658 "%s.rmact_gfx_alt", section));
3659 sz_strlcpy(pextra->rmact_gfx_alt2,
3661 "%s.rmact_gfx_alt2", section));
3662 sz_strlcpy(pextra->graphic_str,
3663 secfile_lookup_str_default(file, "-", "%s.graphic", section));
3664 sz_strlcpy(pextra->graphic_alt,
3666 "%s.graphic_alt", section));
3667
3668 reqs = lookup_req_list(file, compat, section, "reqs", extra_rule_name(pextra));
3669 if (reqs == NULL) {
3670 ok = FALSE;
3671 break;
3672 }
3673 requirement_vector_copy(&pextra->reqs, reqs);
3674
3675 reqs = lookup_req_list(file, compat, section, "rmreqs", extra_rule_name(pextra));
3676 if (reqs == NULL) {
3677 ok = FALSE;
3678 break;
3679 }
3680 requirement_vector_copy(&pextra->rmreqs, reqs);
3681
3682 reqs = lookup_req_list(file, compat, section, "appearance_reqs", extra_rule_name(pextra));
3683 if (reqs == NULL) {
3684 ok = FALSE;
3685 break;
3686 }
3687 requirement_vector_copy(&pextra->appearance_reqs, reqs);
3688
3689 reqs = lookup_req_list(file, compat, section, "disappearance_reqs", extra_rule_name(pextra));
3690 if (reqs == NULL) {
3691 ok = FALSE;
3692 break;
3693 }
3694 requirement_vector_copy(&pextra->disappearance_reqs, reqs);
3695
3696 pextra->buildable = secfile_lookup_bool_default(file,
3698 "%s.buildable", section);
3699 pextra->generated = secfile_lookup_bool_default(file, TRUE,
3700 "%s.generated", section);
3701
3702 pextra->build_time = 0; /* default */
3703 lookup_time(file, &pextra->build_time, section, "build_time",
3704 filename, extra_rule_name(pextra), &ok);
3705 pextra->build_time_factor = secfile_lookup_int_default(file, 1,
3706 "%s.build_time_factor", section);
3707 pextra->removal_time = 0; /* default */
3708 lookup_time(file, &pextra->removal_time, section, "removal_time",
3709 filename, extra_rule_name(pextra), &ok);
3710 pextra->removal_time_factor = secfile_lookup_int_default(file, 1,
3711 "%s.removal_time_factor", section);
3712 pextra->infracost = secfile_lookup_int_default(file, 0,
3713 "%s.infracost", section);
3714 if (pextra->infracost > 0) {
3715 terrain_control.infrapoints = TRUE;
3716 }
3717
3718 pextra->defense_bonus = secfile_lookup_int_default(file, 0,
3719 "%s.defense_bonus",
3720 section);
3721 if (pextra->defense_bonus != 0) {
3722 if (extra_has_flag(pextra, EF_NATURAL_DEFENSE)) {
3724 } else {
3726 }
3727 }
3728
3729 eus_name = secfile_lookup_str_default(file, "Normal", "%s.unit_seen", section);
3731 if (!extra_unit_seen_type_is_valid(pextra->eus)) {
3733 "\"%s\" extra \"%s\" has illegal unit_seen value \"%s\".",
3734 filename, extra_rule_name(pextra), eus_name);
3735 ok = FALSE;
3736 break;
3737 }
3738 if (pextra->eus == EUS_HIDDEN) {
3740 }
3741
3742 pextra->appearance_chance = secfile_lookup_int_default(file, RS_DEFAULT_EXTRA_APPEARANCE,
3743 "%s.appearance_chance",
3744 section);
3745 pextra->disappearance_chance = secfile_lookup_int_default(file,
3747 "%s.disappearance_chance",
3748 section);
3749
3750 pextra->no_aggr_near_city = secfile_lookup_int_default(file, -1,
3751 "%s.no_aggr_near_city",
3752 section);
3753
3754 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
3755 BV_CLR_ALL(pextra->native_to);
3756 for (j = 0; j < nval; j++) {
3757 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
3758
3759 if (uclass == NULL) {
3761 "\"%s\" extra \"%s\" is native to unknown unit class \"%s\".",
3762 filename, extra_rule_name(pextra), slist[j]);
3763 ok = FALSE;
3764 break;
3765 } else {
3766 BV_SET(pextra->native_to, uclass_index(uclass));
3767 }
3768 }
3769 free(slist);
3770
3771 if (!ok) {
3772 break;
3773 }
3774
3775 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
3776 BV_CLR_ALL(pextra->flags);
3777 for (j = 0; j < nval; j++) {
3778 const char *sval = slist[j];
3779 enum extra_flag_id flag;
3780
3782
3783 if (!extra_flag_id_is_valid(flag)) {
3785 "\"%s\" extra \"%s\": unknown flag \"%s\".",
3786 filename, extra_rule_name(pextra), sval);
3787 ok = FALSE;
3788 break;
3789 } else {
3790 BV_SET(pextra->flags, flag);
3791 }
3792 }
3793 free(slist);
3794
3795 if (pextra->no_aggr_near_city >= 0) {
3797 }
3798
3799 if (extra_has_flag(pextra, EF_CAUSE_ZOC)) {
3801 }
3802
3803 if (!ok) {
3804 break;
3805 }
3806
3807 slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
3808 for (j = 0; j < nval; j++) {
3809 const char *sval = slist[j];
3811
3812 if (pextra2 == NULL) {
3814 "\"%s\" extra \"%s\": unknown conflict extra \"%s\".",
3815 filename, extra_rule_name(pextra), sval);
3816 ok = FALSE;
3817 break;
3818 } else {
3819 BV_SET(pextra->conflicts, extra_index(pextra2));
3820 BV_SET(pextra2->conflicts, extra_index(pextra));
3821 }
3822 }
3823
3824 free(slist);
3825
3826 if (!ok) {
3827 break;
3828 }
3829
3830 slist = secfile_lookup_str_vec(file, &nval, "%s.hidden_by", section);
3831 BV_CLR_ALL(pextra->hidden_by);
3832 for (j = 0; j < nval; j++) {
3833 const char *sval = slist[j];
3834 const struct extra_type *top = extra_type_by_rule_name(sval);
3835
3836 if (top == NULL) {
3838 "\"%s\" extra \"%s\" hidden by unknown extra \"%s\".",
3839 filename, extra_rule_name(pextra), sval);
3840 ok = FALSE;
3841 break;
3842 } else {
3843 BV_SET(pextra->hidden_by, extra_index(top));
3844 }
3845 }
3846 free(slist);
3847
3848 if (!ok) {
3849 break;
3850 }
3851
3852 slist = secfile_lookup_str_vec(file, &nval, "%s.bridged_over", section);
3853 BV_CLR_ALL(pextra->bridged_over);
3854 for (j = 0; j < nval; j++) {
3855 const char *sval = slist[j];
3856 const struct extra_type *top = extra_type_by_rule_name(sval);
3857
3858 if (top == NULL) {
3860 "\"%s\" extra \"%s\" bridged over unknown extra \"%s\".",
3861 filename, extra_rule_name(pextra), sval);
3862 ok = FALSE;
3863 break;
3864 } else {
3865 BV_SET(pextra->bridged_over, extra_index(top));
3866 }
3867 }
3868 free(slist);
3869
3870 if (!ok) {
3871 break;
3872 }
3873
3875 "%s.visibility_req", section);
3877
3878 if (vis_req == NULL) {
3880 "\"%s\" %s: unknown visibility_req %s.",
3881 filename, section, vis_req_name);
3882 ok = FALSE;
3883 break;
3884 }
3885
3886 pextra->visibility_req = advance_number(vis_req);
3887
3888 pextra->helptext = lookup_strvec(file, section, "helptext");
3890 }
3891
3892 if (ok) {
3893 int i = 0;
3894 /* Resource details */
3895
3897 char identifier[MAX_LEN_NAME];
3898 const char *id;
3900
3901 if (!presource->data.resource) {
3903 "\"%s\" extra \"%s\" has \"Resource\" cause but no "
3904 "corresponding [resource_*] section",
3905 filename, extra_rule_name(presource));
3906 ok = FALSE;
3907 break;
3908 }
3909
3911 presource->data.resource->output[o] =
3912 secfile_lookup_int_default(file, 0, "%s.%s", rsection,
3915
3916 id = secfile_lookup_str_default(file, NULL, "%s.identifier", rsection);
3917
3918 if (id == NULL) {
3919 presource->data.resource->id_old_save = '\0';
3920 } else {
3921 sz_strlcpy(identifier, id);
3922
3923 presource->data.resource->id_old_save = identifier[0];
3924 if (RESOURCE_NULL_IDENTIFIER == presource->data.resource->id_old_save) {
3926 "\"%s\" [%s] identifier missing value.",
3927 filename, rsection);
3928 ok = FALSE;
3929 break;
3930 }
3931 if (RESOURCE_NONE_IDENTIFIER == presource->data.resource->id_old_save) {
3933 "\"%s\" [%s] cannot use '%c' as an identifier;"
3934 " it is reserved.",
3935 filename, rsection, presource->data.resource->id_old_save);
3936 ok = FALSE;
3937 break;
3938 }
3939 }
3940
3941 if (!ok) {
3942 break;
3943 }
3944
3945 i++;
3947
3948 for (j = 0; ok && j < game.control.num_resource_types; j++) {
3949 const char *section = &resource_sections[j * MAX_SECTION_LABEL];
3950 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
3952
3953 if (!is_extra_caused_by(pextra, EC_RESOURCE)) {
3955 "\"%s\" resource section [%s]: extra \"%s\" does not "
3956 "have \"Resource\" in its causes",
3957 filename, section, extra_name);
3958 ok = FALSE;
3959 }
3960 }
3961 }
3962
3963 if (ok) {
3964 /* This can't be part of previous loop as we don't want random data from previous
3965 * ruleset to play havoc on us when we have only some resource identifiers loaded
3966 * from the new ruleset. */
3968 if (pres->data.resource->id_old_save != '\0') {
3970 if (pres->data.resource->id_old_save == pres2->data.resource->id_old_save
3971 && pres != pres2) {
3973 "\"%s\" [%s] has the same identifier as [%s].",
3974 filename,
3977 ok = FALSE;
3978 break;
3979 }
3981
3982 if (!ok) {
3983 break;
3984 }
3985 }
3987 }
3988
3989 if (ok) {
3990 /* Base details */
3992 struct base_type *pbase = extra_base_get(pextra);
3993 const char *section;
3994 const char *gui_str;
3995
3996 if (!pbase) {
3998 "\"%s\" extra \"%s\" has \"Base\" cause but no "
3999 "corresponding [base_*] section",
4000 filename, extra_rule_name(pextra));
4001 ok = FALSE;
4002 break;
4003 }
4005
4006 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4008 if (!base_gui_type_is_valid(pbase->gui_type)) {
4010 "\"%s\" base \"%s\": unknown gui_type \"%s\".",
4011 filename, extra_rule_name(pextra), gui_str);
4012 ok = FALSE;
4013 break;
4014 }
4015
4016 pbase->border_sq = secfile_lookup_int_default(file, -1, "%s.border_sq",
4017 section);
4018 pbase->vision_main_sq = secfile_lookup_int_default(file, -1,
4019 "%s.vision_main_sq",
4020 section);
4021 pbase->vision_invis_sq = secfile_lookup_int_default(file, -1,
4022 "%s.vision_invis_sq",
4023 section);
4024 pbase->vision_subs_sq = secfile_lookup_int_default(file, -1,
4025 "%s.vision_subs_sq",
4026 section);
4027
4028 if (!ok) {
4029 break;
4030 }
4031
4034
4036 struct base_type *pbase2;
4037
4038 if (pextra == pextra2) {
4039 /* End of the fully initialized bases iteration. */
4040 break;
4041 }
4042
4045 BV_SET(pextra->conflicts, extra_index(pextra2));
4046 BV_SET(pextra2->conflicts, extra_index(pextra));
4047 }
4049 }
4051
4052 for (j = 0; ok && j < game.control.num_base_types; j++) {
4053 const char *section = &base_sections[j * MAX_SECTION_LABEL];
4054 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4056
4057 if (!is_extra_caused_by(pextra, EC_BASE)) {
4059 "\"%s\" base section [%s]: extra \"%s\" does not have "
4060 "\"Base\" in its causes",
4061 filename, section, extra_name);
4062 ok = FALSE;
4063 }
4064 }
4065 }
4066
4067 if (ok) {
4069 struct road_type *proad = extra_road_get(pextra);
4070 const char *section;
4071 const char **slist;
4072 const char *special;
4073 const char *modestr;
4074 struct requirement_vector *reqs;
4075 const char *gui_str;
4076
4077 if (!proad) {
4079 "\"%s\" extra \"%s\" has \"Road\" cause but no "
4080 "corresponding [road_*] section",
4081 filename, extra_rule_name(pextra));
4082 ok = FALSE;
4083 break;
4084 }
4086
4087 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4089 if (!road_gui_type_is_valid(proad->gui_type)) {
4091 "\"%s\" road \"%s\": unknown gui_type \"%s\".",
4092 filename, extra_rule_name(pextra), gui_str);
4093 ok = FALSE;
4094 break;
4095 }
4096
4097 reqs = lookup_req_list(file, compat, section, "first_reqs", extra_rule_name(pextra));
4098 if (reqs == NULL) {
4099 ok = FALSE;
4100 break;
4101 }
4102 requirement_vector_copy(&proad->first_reqs, reqs);
4103
4104 if (!secfile_lookup_int(file, &proad->move_cost,
4105 "%s.move_cost", section)) {
4106 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4107 ok = FALSE;
4108 break;
4109 }
4110
4111 modestr = secfile_lookup_str_default(file, "FastAlways", "%s.move_mode",
4112 section);
4114 if (!road_move_mode_is_valid(proad->move_mode)) {
4116 "Illegal move_mode \"%s\" for road \"%s\"",
4117 modestr, extra_rule_name(pextra));
4118 ok = FALSE;
4119 break;
4120 }
4121
4123 proad->tile_incr_const[o] =
4124 secfile_lookup_int_default(file, 0, "%s.%s_incr_const",
4126 proad->tile_incr[o] =
4127 secfile_lookup_int_default(file, 0, "%s.%s_incr",
4129 proad->tile_bonus[o] =
4130 secfile_lookup_int_default(file, 0, "%s.%s_bonus",
4133
4134 special = secfile_lookup_str_default(file, "None", "%s.compat_special", section);
4135 if (!fc_strcasecmp(special, "Road")) {
4136 if (compat_road) {
4138 "Multiple roads marked as compatibility \"Road\"");
4139 ok = FALSE;
4140 }
4141 compat_road = TRUE;
4142 proad->compat = ROCO_ROAD;
4143 } else if (!fc_strcasecmp(special, "Railroad")) {
4144 if (compat_rail) {
4146 "Multiple roads marked as compatibility \"Railroad\"");
4147 ok = FALSE;
4148 }
4149 compat_rail = TRUE;
4150 proad->compat = ROCO_RAILROAD;
4151 } else if (!fc_strcasecmp(special, "River")) {
4152 if (compat_river) {
4154 "Multiple roads marked as compatibility \"River\"");
4155 ok = FALSE;
4156 }
4158 proad->compat = ROCO_RIVER;
4159 } else if (!fc_strcasecmp(special, "None")) {
4160 proad->compat = ROCO_NONE;
4161 } else {
4163 "Illegal compatibility special \"%s\" for road %s",
4164 special, extra_rule_name(pextra));
4165 ok = FALSE;
4166 }
4167
4168 if (!ok) {
4169 break;
4170 }
4171
4172 slist = secfile_lookup_str_vec(file, &nval, "%s.integrates", section);
4173 BV_CLR_ALL(proad->integrates);
4174 for (j = 0; j < nval; j++) {
4175 const char *sval = slist[j];
4177 struct road_type *top = NULL;
4178
4179 if (textra != NULL) {
4180 top = extra_road_get(textra);
4181 }
4182
4183 if (top == NULL) {
4185 "\"%s\" road \"%s\" integrates with unknown road \"%s\".",
4186 filename, extra_rule_name(pextra), sval);
4187 ok = FALSE;
4188 break;
4189 } else {
4190 BV_SET(proad->integrates, road_number(top));
4191 }
4192 }
4193 free(slist);
4194
4195 if (!ok) {
4196 break;
4197 }
4198
4199 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
4200 BV_CLR_ALL(proad->flags);
4201 for (j = 0; j < nval; j++) {
4202 const char *sval = slist[j];
4204
4205 if (!road_flag_id_is_valid(flag)) {
4207 "\"%s\" road \"%s\": unknown flag \"%s\".",
4208 filename, extra_rule_name(pextra), sval);
4209 ok = FALSE;
4210 break;
4211 } else {
4212 BV_SET(proad->flags, flag);
4213 }
4214 }
4215 free(slist);
4216
4217 if (!ok) {
4218 break;
4219 }
4221
4222 for (j = 0; ok && j < game.control.num_road_types; j++) {
4223 const char *section = &road_sections[j * MAX_SECTION_LABEL];
4224 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4226
4227 if (!is_extra_caused_by(pextra, EC_ROAD)) {
4229 "\"%s\" road section [%s]: extra \"%s\" does not have "
4230 "\"Road\" in its causes",
4231 filename, section, extra_name);
4232 ok = FALSE;
4233 }
4234 }
4235 }
4236
4237 if (ok) {
4238 extra_type_iterate(pextra) {
4239 pextra->bridged = extra_type_list_new();
4241 if (BV_ISSET(pextra->bridged_over, pbridged->id)) {
4242 extra_type_list_append(pextra->bridged, pbridged);
4243 }
4246 }
4247
4248 if (ok) {
4250 }
4251
4252 return ok;
4253}
4254
4255/**********************************************************************/
4259static bool load_government_names(struct section_file *file,
4260 struct rscompat_info *compat)
4261{
4262 int nval = 0;
4263 struct section_list *sec;
4264 const char *filename = secfile_name(file);
4265 bool ok = TRUE;
4266
4267 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4268 return FALSE;
4269 }
4270
4271 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4272 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4273
4275 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
4276 ruleset_error(NULL, LOG_ERROR, "\"%s\": No governments?!?", filename);
4277 ok = FALSE;
4278 } else if (nval > G_LAST) {
4280 "\"%s\": Too many governments (%d, max %d)",
4281 filename, nval, G_LAST);
4282 ok = FALSE;
4283 }
4284
4285 if (ok) {
4287
4288 /* Government names are needed early so that get_government_by_name will
4289 * work. */
4290 governments_iterate(gov) {
4291 const char *sec_name =
4293
4294 if (!ruleset_load_names(&gov->name, NULL, file, sec_name)) {
4295 ok = FALSE;
4296 break;
4297 }
4299 }
4300
4302
4303 if (ok) {
4305 nval = (NULL != sec ? section_list_size(sec) : 0);
4306
4307 if (nval > MAX_NUM_MULTIPLIERS) {
4309 "\"%s\": Too many multipliers (%d, max %d)",
4310 filename, nval, MAX_NUM_MULTIPLIERS);
4311
4312 ok = FALSE;
4313 } else {
4315 }
4316
4317 if (ok) {
4318 multipliers_iterate(pmul) {
4319 const char *sec_name =
4321
4322 if (!ruleset_load_names(&pmul->name, NULL, file, sec_name)) {
4324 "\"%s\": Cannot load multiplier names",
4325 filename);
4326 ok = FALSE;
4327 break;
4328 }
4330 }
4331 }
4332
4334
4335 return ok;
4336}
4337
4338/**********************************************************************/
4342 struct rscompat_info *compat)
4343{
4344 struct section_list *sec;
4345 const char *filename = secfile_name(file);
4346 bool ok = TRUE;
4347
4349
4351 = lookup_government(file, "governments.during_revolution", filename, NULL);
4353 ok = FALSE;
4354 }
4355
4356 if (ok) {
4359
4360 /* Easy ones: */
4362 const int i = government_index(g);
4363 const char *sec_name = section_name(section_list_get(sec, i));
4364 struct requirement_vector *reqs
4366
4367 if (reqs == NULL) {
4368 ok = FALSE;
4369 break;
4370 }
4371
4372 if (NULL != secfile_entry_lookup(file, "%s.ai_better", sec_name)) {
4373 char entry[100];
4374
4375 fc_snprintf(entry, sizeof(entry), "%s.ai_better", sec_name);
4376 g->ai.better = lookup_government(file, entry, filename, NULL);
4377 if (g->ai.better == NULL) {
4378 ok = FALSE;
4379 break;
4380 }
4381 } else {
4382 g->ai.better = NULL;
4383 }
4384 requirement_vector_copy(&g->reqs, reqs);
4385
4386 sz_strlcpy(g->graphic_str,
4387 secfile_lookup_str(file, "%s.graphic", sec_name));
4388 sz_strlcpy(g->graphic_alt,
4389 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
4390 sz_strlcpy(g->sound_str,
4391 secfile_lookup_str_default(file, "-", "%s.sound", sec_name));
4392 sz_strlcpy(g->sound_alt,
4393 secfile_lookup_str_default(file, "-", "%s.sound_alt", sec_name));
4394 sz_strlcpy(g->sound_alt2,
4395 secfile_lookup_str_default(file, "-", "%s.sound_alt2", sec_name));
4396
4397 g->helptext = lookup_strvec(file, sec_name, "helptext");
4399 }
4400
4401
4402 if (ok) {
4403 /* Titles */
4405 const char *sec_name
4407 const char *male, *female;
4408
4409 if (!(male = secfile_lookup_str(file, "%s.ruler_male_title", sec_name))
4410 || !(female = secfile_lookup_str(file, "%s.ruler_female_title",
4411 sec_name))) {
4413 "Lack of default ruler titles for "
4414 "government \"%s\" (nb %d): %s",
4416 secfile_error());
4417 ok = FALSE;
4418 break;
4419 } else if (NULL == government_ruler_title_new(g, NULL, male, female)) {
4421 "Lack of default ruler titles for "
4422 "government \"%s\" (nb %d).",
4424 ok = FALSE;
4425 break;
4426 }
4428 }
4429
4431
4432 if (ok) {
4434 multipliers_iterate(pmul) {
4435 int id = multiplier_index(pmul);
4436 const char *sec_name = section_name(section_list_get(sec, id));
4437 struct requirement_vector *reqs;
4438
4439 if (!secfile_lookup_int(file, &pmul->start, "%s.start", sec_name)) {
4440 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4441 ok = FALSE;
4442 break;
4443 }
4444 if (!secfile_lookup_int(file, &pmul->stop, "%s.stop", sec_name)) {
4445 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4446 ok = FALSE;
4447 break;
4448 }
4449 if (pmul->stop <= pmul->start) {
4451 "Multiplier \"%s\" stop (%d) must be greater "
4452 "than start (%d)", multiplier_rule_name(pmul),
4453 pmul->stop, pmul->start);
4454 ok = FALSE;
4455 break;
4456 }
4457 if (!secfile_lookup_int(file, &pmul->step, "%s.step", sec_name)) {
4458 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4459 ok = FALSE;
4460 break;
4461 }
4462 if (((pmul->stop - pmul->start) % pmul->step) != 0) {
4464 "Multiplier \"%s\" step (%d) does not fit "
4465 "exactly into interval start-stop (%d to %d)",
4466 multiplier_rule_name(pmul), pmul->step,
4467 pmul->start, pmul->stop);
4468 ok = FALSE;
4469 break;
4470 }
4471 if (!secfile_lookup_int(file, &pmul->def, "%s.default", sec_name)) {
4472 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4473 ok = FALSE;
4474 break;
4475 }
4476 if (pmul->def < pmul->start || pmul->def > pmul->stop) {
4478 "Multiplier \"%s\" default (%d) not within "
4479 "legal range (%d to %d)", multiplier_rule_name(pmul),
4480 pmul->def, pmul->start, pmul->stop);
4481 ok = FALSE;
4482 break;
4483 }
4484 if (((pmul->def - pmul->start) % pmul->step) != 0) {
4486 "Multiplier \"%s\" default (%d) not legal "
4487 "with respect to step size %d",
4488 multiplier_rule_name(pmul), pmul->def, pmul->step);
4489 ok = FALSE;
4490 break;
4491 }
4492 pmul->offset = secfile_lookup_int_default(file, 0,
4493 "%s.offset", sec_name);
4494 pmul->factor = secfile_lookup_int_default(file, 100,
4495 "%s.factor", sec_name);
4496 if (pmul->factor == 0) {
4498 "Multiplier \"%s\" scaling factor must "
4499 "not be zero", multiplier_rule_name(pmul));
4500 ok = FALSE;
4501 break;
4502 }
4503
4504 pmul->minimum_turns = secfile_lookup_int_default(file, 0,
4505 "%s.minimum_turns",
4506 sec_name);
4507
4508 reqs = lookup_req_list(file, compat, sec_name, "reqs",
4509 multiplier_rule_name(pmul));
4510 if (reqs == NULL) {
4511 ok = FALSE;
4512 break;
4513 }
4514 requirement_vector_copy(&pmul->reqs, reqs);
4515
4516 pmul->helptext = lookup_strvec(file, sec_name, "helptext");
4519 }
4520
4521 if (ok) {
4523 }
4524
4525 return ok;
4526}
4527
4528/**********************************************************************/
4539static void send_ruleset_control(struct conn_list *dest)
4540{
4542 int idx = 0;
4543
4545
4546 if (game.ruleset_summary != NULL) {
4547 struct packet_ruleset_summary summary;
4548
4550
4551 lsend_packet_ruleset_summary(dest, &summary);
4552 }
4553
4554 while (desc_left > 0) {
4556 int this_len = desc_left;
4557
4558 if (this_len > MAX_LEN_CONTENT - 21) {
4560 }
4561
4562 part.text[this_len] = '\0';
4563
4565 idx += this_len;
4567
4569 }
4570}
4571
4572/**********************************************************************/
4577static const char *check_leader_names(struct nation_type *pnation)
4578{
4580 const char *name = nation_leader_name(pleader);
4581
4583 if (prev_leader == pleader) {
4584 break;
4585 } else if (0 == fc_strcasecmp(name, nation_leader_name(prev_leader))) {
4586 return name;
4587 }
4590 return NULL;
4591}
4592
4593/**********************************************************************/
4597static bool load_nation_names(struct section_file *file,
4598 struct rscompat_info *compat)
4599{
4600 struct section_list *sec;
4601 int j;
4602 bool ok = TRUE;
4603 const char *filename = secfile_name(file);
4604
4605 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4606 return FALSE;
4607 }
4608
4609 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4610 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4611
4613 if (NULL == sec) {
4615 "No available nations in this ruleset!");
4616 ok = FALSE;
4617 } else if (section_list_size(sec) > MAX_NUM_NATIONS) {
4619 "Too many nations (max %d, we have %d)!",
4621 ok = FALSE;
4622 } else {
4625
4627 const int i = nation_index(pl);
4628 const char *sec_name = section_name(section_list_get(sec, i));
4629 const char *domain = secfile_lookup_str_default(file, NULL,
4630 "%s.translation_domain", sec_name);
4631 const char *noun_plural = secfile_lookup_str(file,
4632 "%s.plural", sec_name);
4633
4634
4635 if (domain == NULL) {
4636 domain = "freeciv-nations";
4637 }
4638
4639 if (!strcmp("freeciv-core", domain)) {
4640 pl->translation_domain = NULL;
4641 } else if (!strcmp("freeciv-nations", domain)) {
4642 pl->translation_domain = fc_strdup(domain);
4643 } else {
4645 "Unsupported translation domain \"%s\" for %s",
4646 domain, sec_name);
4647 ok = FALSE;
4648 break;
4649 }
4650
4651 if (!ruleset_load_names(&pl->adjective, pl->translation_domain, file, sec_name)) {
4652 ok = FALSE;
4653 break;
4654 }
4655 name_set(&pl->noun_plural, pl->translation_domain, noun_plural);
4656
4657 /* Check if nation name is already defined. */
4658 for (j = 0; j < i && ok; j++) {
4659 struct nation_type *n2 = nation_by_number(j);
4660
4661 /* Compare strings after stripping off qualifiers -- we don't want
4662 * two nations to end up with identical adjectives displayed to users.
4663 * (This check only catches English, not localisations, of course.) */
4664 if (0 == strcmp(Qn_(untranslated_name(&n2->adjective)),
4665 Qn_(untranslated_name(&pl->adjective)))) {
4667 "Two nations defined with the same adjective \"%s\": "
4668 "in section \'%s\' and section \'%s\'",
4669 Qn_(untranslated_name(&pl->adjective)),
4671 ok = FALSE;
4672 } else if (!strcmp(rule_name_get(&n2->adjective),
4673 rule_name_get(&pl->adjective))) {
4674 /* We cannot have the same rule name, as the game needs them to be
4675 * distinct. */
4677 "Two nations defined with the same rule_name \"%s\": "
4678 "in section \'%s\' and section \'%s\'",
4679 rule_name_get(&pl->adjective),
4681 ok = FALSE;
4682 } else if (0 == strcmp(Qn_(untranslated_name(&n2->noun_plural)),
4683 Qn_(untranslated_name(&pl->noun_plural)))) {
4684 /* We don't want identical English plural names either. */
4686 "Two nations defined with the same plural name \"%s\": "
4687 "in section \'%s\' and section \'%s\'",
4688 Qn_(untranslated_name(&pl->noun_plural)),
4690 ok = FALSE;
4691 }
4692 }
4693 if (!ok) {
4694 break;
4695 }
4697 }
4698
4700
4701 if (ok) {
4703 if (sec != NULL) {
4705
4706 section_list_iterate(sec, psection) {
4707 struct nation_group *pgroup;
4708 const char *name;
4709
4710 name = secfile_lookup_str(file, "%s.name", section_name(psection));
4711 if (NULL == name) {
4712 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4713 ok = FALSE;
4714 break;
4715 }
4717 if (pgroup == NULL) {
4718 ok = FALSE;
4719 break;
4720 }
4723 sec = NULL;
4724 }
4725 }
4726
4727 return ok;
4728}
4729
4730/**********************************************************************/
4733static bool is_on_allowed_list(const char *name, const char **list, size_t len)
4734{
4735 int i;
4736
4737 for (i = 0; i < len; i++) {
4738 if (!fc_strcasecmp(name, list[i])) {
4739 return TRUE;
4740 }
4741 }
4742 return FALSE;
4743}
4744
4745/**********************************************************************/
4749static bool load_city_name_list(struct section_file *file,
4750 struct nation_type *pnation,
4751 const char *secfile_str1,
4752 const char *secfile_str2,
4753 const char **allowed_terrains,
4754 size_t atcount)
4755{
4756 size_t dim, j;
4757 bool ok = TRUE;
4758 const char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
4760
4761 /* Each string will be of the form "<cityname> (<label>, <label>, ...)".
4762 * The cityname is just the name for this city, while each "label" matches
4763 * a terrain type for the city (or "river"), with a preceding ! to negate
4764 * it. The parentheses are optional (but necessary to have the settings,
4765 * of course). Our job is now to parse it. */
4766 for (j = 0; j < dim; j++) {
4767 size_t len = strlen(cities[j]);
4768 char city_name[len + 1], *p, *next, *end;
4769 struct nation_city *pncity;
4770
4772
4773 /* Now we wish to determine values for all of the city labels. A value
4774 * of NCP_NONE means no preference (which is necessary so that the use
4775 * of this is optional); NCP_DISLIKE means the label is negated and
4776 * NCP_LIKE means it's labelled. Mostly the parsing just involves
4777 * a lot of ugly string handling... */
4778 if ((p = strchr(city_name, '('))) {
4779 *p++ = '\0';
4780
4781 if (!(end = strchr(p, ')'))) {
4783 "\"%s\" [%s] %s: city name \"%s\" "
4784 "unmatched parenthesis.", secfile_name(file),
4786 ok = FALSE;
4787 } else {
4788 for (*end++ = '\0'; '\0' != *end; end++) {
4789 if (!fc_isspace(*end)) {
4791 "\"%s\" [%s] %s: city name \"%s\" "
4792 "contains characters after last parenthesis.",
4794 cities[j]);
4795 ok = FALSE;
4796 break;
4797 }
4798 }
4799 }
4800 }
4801
4802 /* Build the nation_city. */
4805 /* The ruleset contains a name that is too long. This shouldn't
4806 * happen - if it does, the author should get immediate feedback. */
4808 "\"%s\" [%s] %s: city name \"%s\" is too long.",
4809 secfile_name(file),
4811 ok = FALSE;
4812 city_name[MAX_LEN_CITYNAME - 1] = '\0';
4813 }
4814 pncity = nation_city_new(pnation, city_name);
4815
4816 if (NULL != p) {
4817 /* Handle the labels one at a time. */
4818 do {
4819 enum nation_city_preference prefer;
4820
4821 if ((next = strchr(p, ','))) {
4822 *next = '\0';
4823 }
4825
4826 /* The ! is used to mark a negative, which is recorded with
4827 * NCP_DISLIKE. Otherwise we use a NCP_LIKE.
4828 */
4829 if (*p == '!') {
4830 p++;
4831 prefer = NCP_DISLIKE;
4832 } else {
4833 prefer = NCP_LIKE;
4834 }
4835
4836 if (0 == fc_strcasecmp(p, "river")) {
4838 && !is_on_allowed_list(p,
4841 "\"%s\" [%s] %s: city \"%s\" "
4842 "has terrain hint \"%s\" not in allowed_terrains.",
4844 city_name, p);
4845 ok = FALSE;
4846 } else {
4848 }
4849 } else {
4850 const struct terrain *pterrain = terrain_by_rule_name(p);
4851
4852 if (NULL == pterrain) {
4853 /* Try with removing frequent trailing 's'. */
4854 size_t l = strlen(p);
4855
4856 if (0 < l && 's' == fc_tolower(p[l - 1])) {
4857 char saved = p[l - 1];
4858
4859 p[l - 1] = '\0';
4860 pterrain = terrain_by_rule_name(p);
4861 if (pterrain == NULL) {
4862 /* Didn't help, restore for later allowed_terrains check */
4863 p[l - 1] = saved;
4864 }
4865 }
4866 }
4867
4868 /* Nationset may have been devised with a specific set of terrains
4869 * in mind which don't quite match this ruleset, in which case we
4870 * (a) quietly ignore any hints mentioned that don't happen to be in
4871 * the current ruleset, (b) enforce that terrains mentioned by nations
4872 * must be on the list */
4873 if (pterrain != NULL && game.server.ruledit.allowed_terrains != NULL) {
4874 if (!is_on_allowed_list(p,
4876 /* Terrain exists, but not intended for these nations */
4878 "\"%s\" [%s] %s: city \"%s\" "
4879 "has terrain hint \"%s\" not in allowed_terrains.",
4881 city_name, p);
4882 ok = FALSE;
4883 break;
4884 }
4885 } else if (!pterrain) {
4886 /* Terrain doesn't exist; only complain if it's not on any list */
4888 || !is_on_allowed_list(p,
4891 "\"%s\" [%s] %s: city \"%s\" "
4892 "has unknown terrain hint \"%s\".",
4894 city_name, p);
4895 ok = FALSE;
4896 break;
4897 }
4898 }
4899 if (NULL != pterrain) {
4900 nation_city_set_terrain_preference(pncity, pterrain, prefer);
4901 }
4902 }
4903
4904 p = next ? next + 1 : NULL;
4905 } while (NULL != p && '\0' != *p);
4906 }
4907 }
4908
4909 if (NULL != cities) {
4910 free(cities);
4911 }
4912
4913 return ok;
4914}
4915
4916/**********************************************************************/
4919static bool load_ruleset_nations(struct section_file *file,
4920 struct rscompat_info *compat)
4921{
4922 struct government *gov;
4923 int j;
4924 size_t dim;
4925 char temp_name[MAX_LEN_NAME];
4926 const char **vec;
4927 const char *name, *bad_leader;
4928 const char *sval;
4929 int default_set;
4930 const char *filename = secfile_name(file);
4931 struct section_list *sec = NULL;
4932 enum trait tr;
4933 bool ok = TRUE;
4934
4935 name = secfile_lookup_str_default(file, NULL, "ruledit.nationlist");
4936 if (name != NULL) {
4938 }
4940 "ruledit.embedded_nations");
4941
4942 if (vec != NULL) {
4943 /* Copy to persistent vector */
4946
4947 for (j = 0; j < game.server.ruledit.embedded_nations_count; j++) {
4949 }
4950
4951 free(vec);
4952 }
4953
4955
4956 ruleset_load_traits(game.server.default_traits, file, "default_traits", "");
4957 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
4958 if (game.server.default_traits[tr].min < 0) {
4960 }
4961 if (game.server.default_traits[tr].max < 0) {
4963 }
4964 if (game.server.default_traits[tr].fixed < 0) {
4966
4967 /* TODO: Should sometimes round the a / 2 = x.5 results up */
4969 }
4972 "Default values for trait %s not sane.",
4973 trait_name(tr));
4974 ok = FALSE;
4975 break;
4976 }
4977 }
4978
4979 if (ok) {
4981 "compatibility.allowed_govs");
4982 if (vec != NULL) {
4983 /* Copy to persistent vector */
4985 = fc_malloc(game.server.ruledit.ag_count * sizeof(char *));
4987 (const char **)game.server.ruledit.nc_agovs;
4988
4989 for (j = 0; j < game.server.ruledit.ag_count; j++) {
4991 }
4992
4993 free(vec);
4994 }
4995
4997 "compatibility.allowed_terrains");
4998 if (vec != NULL) {
4999 /* Copy to persistent vector */
5001 = fc_malloc(game.server.ruledit.at_count * sizeof(char *));
5003 (const char **)game.server.ruledit.nc_aterrs;
5004
5005 for (j = 0; j < game.server.ruledit.at_count; j++) {
5007 }
5008
5009 free(vec);
5010 }
5011
5013 "compatibility.allowed_styles");
5014 if (vec != NULL) {
5015 /* Copy to persistent vector */
5017 = fc_malloc(game.server.ruledit.as_count * sizeof(char *));
5019 (const char **)game.server.ruledit.nc_astyles;
5020
5021 for (j = 0; j < game.server.ruledit.as_count; j++) {
5023 }
5024
5025 free(vec);
5026 }
5027
5029 "compatibility.default_government");
5030 /* We deliberately don't check this against allowed_govs. It's only
5031 * specified once so not vulnerable to typos, and may usefully be set in
5032 * a specific ruleset to a gov not explicitly known by the nation set. */
5033 if (sval != NULL) {
5035 if (game.default_government == NULL) {
5037 "Tried to set unknown government type \"%s\" as default_government!",
5038 sval);
5039 ok = FALSE;
5040 } else {
5043 }
5044 }
5045 }
5046
5047 if (ok) {
5049 if (sec != NULL) {
5051
5052 section_list_iterate(sec, psection) {
5053 const char *set_name, *set_rule_name, *set_description;
5054
5055 set_name = secfile_lookup_str(file, "%s.name", section_name(psection));
5057 secfile_lookup_str(file, "%s.rule_name", section_name(psection));
5058 set_description = secfile_lookup_str_default(file, "", "%s.description",
5059 section_name(psection));
5060 if (NULL == set_name || NULL == set_rule_name) {
5061 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5062 ok = FALSE;
5063 break;
5064 }
5066 ok = FALSE;
5067 break;
5068 }
5071 sec = NULL;
5072 } else {
5074 "At least one nation set [" NATION_SET_SECTION_PREFIX "_*] "
5075 "must be defined.");
5076 ok = FALSE;
5077 }
5078 }
5079
5080 if (ok) {
5081 /* Default set that every nation is a member of. */
5083 "compatibility.default_nationset");
5084 if (sval != NULL) {
5086 if (pset != NULL) {
5088 } else {
5090 "Unknown default_nationset \"%s\".", sval);
5091 ok = FALSE;
5092 }
5093 } else if (nation_set_count() == 1) {
5094 /* If there's only one set defined, every nation is implicitly a
5095 * member of that set. */
5096 default_set = 0;
5097 } else {
5098 /* No default nation set; every nation must explicitly specify at
5099 * least one set to be a member of. */
5100 default_set = -1;
5101 }
5102 }
5103
5104 if (ok) {
5106 if (sec) {
5107 section_list_iterate(sec, psection) {
5108 struct nation_group *pgroup;
5109 bool hidden;
5110
5111 name = secfile_lookup_str(file, "%s.name", section_name(psection));
5113 if (pgroup == NULL) {
5114 ok = FALSE;
5115 break;
5116 }
5117
5118 hidden = secfile_lookup_bool_default(file, FALSE, "%s.hidden",
5119 section_name(psection));
5121
5122 if (!secfile_lookup_int(file, &j, "%s.match", section_name(psection))) {
5123 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5124 ok = FALSE;
5125 break;
5126 }
5130 sec = NULL;
5131 }
5132 }
5133
5134 if (ok) {
5136 nations_iterate(pnation) {
5137 struct nation_type *pconflict;
5138 const int i = nation_index(pnation);
5139 char tmp[200] = "\0";
5140 const char *barb_type;
5141 const char *sec_name = section_name(section_list_get(sec, i));
5142 const char *legend;
5143
5144 /* Nation sets and groups. */
5145 if (default_set >= 0) {
5146 nation_set_list_append(pnation->sets,
5148 }
5149 vec = secfile_lookup_str_vec(file, &dim, "%s.groups", sec_name);
5150 for (j = 0; j < dim; j++) {
5151 struct nation_set *pset = nation_set_by_rule_name(vec[j]);
5153
5154 fc_assert(pset == NULL || pgroup == NULL);
5155
5156 if (NULL != pset) {
5157 nation_set_list_append(pnation->sets, pset);
5158 } else if (NULL != pgroup) {
5159 nation_group_list_append(pnation->groups, pgroup);
5160 } else {
5161 /* For nation authors, this would probably be considered an error.
5162 * But it can happen normally. The civ1 compatibility ruleset only
5163 * uses the nations that were in civ1, so not all of the links will
5164 * exist. */
5165 log_verbose("Nation %s: Unknown set/group \"%s\".",
5166 nation_rule_name(pnation), vec[j]);
5167 }
5168 }
5169 if (NULL != vec) {
5170 free(vec);
5171 }
5172 if (nation_set_list_size(pnation->sets) < 1) {
5174 "Nation %s is not a member of any nation set",
5175 nation_rule_name(pnation));
5176 ok = FALSE;
5177 break;
5178 }
5179
5180 /* Nation conflicts. */
5181 vec = secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec_name);
5182 for (j = 0; j < dim; j++) {
5184
5185 if (pnation == pconflict) {
5187 "Nation %s conflicts with itself",
5188 nation_rule_name(pnation));
5189 ok = FALSE;
5190 break;
5191 } else if (NULL != pconflict) {
5192 nation_list_append(pnation->server.conflicts_with, pconflict);
5193 } else {
5194 /* For nation authors, this would probably be considered an error.
5195 * But it can happen normally. The civ1 compatibility ruleset only
5196 * uses the nations that were in civ1, so not all of the links will
5197 * exist. */
5198 log_verbose("Nation %s: conflicts_with nation \"%s\" is unknown.",
5199 nation_rule_name(pnation), vec[j]);
5200 }
5201 }
5202 if (NULL != vec) {
5203 free(vec);
5204 }
5205 if (!ok) {
5206 break;
5207 }
5208
5209 /* Nation leaders. */
5210 for (j = 0; j < MAX_NUM_LEADERS; j++) {
5211 const char *sexstr;
5212 sex_t sex;
5213 bool is_male = FALSE;
5214
5215 name = secfile_lookup_str(file, "%s.leaders%d.name", sec_name, j);
5216 if (NULL == name) {
5217 /* No more to read. */
5218 break;
5219 }
5220
5221 if (check_name(name)) {
5222 /* The ruleset contains a name that is too long. This shouldn't
5223 * happen - if it does, the author should get immediate feedback */
5226 "Nation %s: leader name \"%s\" is too long.",
5227 nation_rule_name(pnation), name);
5228 ok = FALSE;
5229 break;
5230 }
5231
5232 sexstr = secfile_lookup_str(file, "%s.leaders%d.sex", sec_name, j);
5233 if (NULL == sexstr) {
5235 "Nation %s: leader \"%s\": %s.",
5236 nation_rule_name(pnation), name, secfile_error());
5237 ok = FALSE;
5238 break;
5239 }
5240
5242
5243 switch (sex) {
5244 case SEX_MALE:
5245 is_male = TRUE;
5246 break;
5247 case SEX_FEMALE:
5248 is_male = FALSE;
5249 break;
5250 case SEX_UNKNOWN:
5252 "Nation %s: leader \"%s\" has unsupported "
5253 "sex variant \"%s\".",
5254 nation_rule_name(pnation), name, sexstr);
5255 ok = FALSE;
5256 break;
5257 }
5258
5259 if (ok) {
5260 (void) nation_leader_new(pnation, name, is_male);
5261 }
5262 }
5263 if (!ok) {
5264 break;
5265 }
5266
5267 /* Check the number of leaders. */
5268 if (MAX_NUM_LEADERS == j) {
5269 /* Too much leaders, get the real number defined in the ruleset. */
5270 while (NULL != secfile_entry_lookup(file, "%s.leaders%d.name",
5271 sec_name, j)) {
5272 j++;
5273 }
5275 "Nation %s: Too many leaders; max is %d",
5277 ok = FALSE;
5278 break;
5279 } else if (0 == j) {
5281 "Nation %s: no leaders; at least one is required.",
5282 nation_rule_name(pnation));
5283 ok = FALSE;
5284 break;
5285 }
5286
5287 /* Check if leader name is not already defined in this nation. */
5288 if ((bad_leader = check_leader_names(pnation))) {
5290 "Nation %s: leader \"%s\" defined more than once.",
5291 nation_rule_name(pnation), bad_leader);
5292 ok = FALSE;
5293 break;
5294 }
5295
5296 /* Nation player color preference, if any */
5297 fc_assert_ret_val(pnation->server.rgb == NULL, FALSE);
5298 (void) rgbcolor_load(file, &pnation->server.rgb, "%s.color", sec_name);
5299
5300 /* Load nation traits */
5301 ruleset_load_traits(pnation->server.traits, file, sec_name, "trait_");
5302 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5303 bool server_traits_used = TRUE;
5304
5305 if (pnation->server.traits[tr].min < 0) {
5306 pnation->server.traits[tr].min = game.server.default_traits[tr].min;
5307 } else {
5309 }
5310 if (pnation->server.traits[tr].max < 0) {
5311 pnation->server.traits[tr].max = game.server.default_traits[tr].max;
5312 } else {
5314 }
5315 if (pnation->server.traits[tr].fixed < 0) {
5316 if (server_traits_used) {
5317 pnation->server.traits[tr].fixed = game.server.default_traits[tr].fixed;
5318 } else {
5319 int diff = pnation->server.traits[tr].max - pnation->server.traits[tr].min;
5320
5321 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5322 pnation->server.traits[tr].fixed = diff / 2 + pnation->server.traits[tr].min;
5323 }
5324 }
5325 if (pnation->server.traits[tr].max < pnation->server.traits[tr].min) {
5327 "%s values for trait %s not sane.",
5328 nation_rule_name(pnation), trait_name(tr));
5329 ok = FALSE;
5330 break;
5331 }
5332 }
5333
5334 if (!ok) {
5335 break;
5336 }
5337
5338 pnation->is_playable =
5339 secfile_lookup_bool_default(file, TRUE, "%s.is_playable", sec_name);
5340
5341 /* Check barbarian type. Default is "None" meaning not a barbarian */
5342 barb_type = secfile_lookup_str_default(file, "None",
5343 "%s.barbarian_type", sec_name);
5344 pnation->barb_type = barbarian_type_by_name(barb_type, fc_strcasecmp);
5345 if (!barbarian_type_is_valid(pnation->barb_type)) {
5347 "Nation %s, barbarian_type is invalid (\"%s\")",
5348 nation_rule_name(pnation), barb_type);
5349 ok = FALSE;
5350 break;
5351 }
5352
5353 if (pnation->barb_type != NOT_A_BARBARIAN
5354 && pnation->is_playable) {
5355 /* We can't allow players to use barbarian nations, barbarians
5356 * may run out of nations */
5358 "Nation %s marked both barbarian and playable.",
5359 nation_rule_name(pnation));
5360 ok = FALSE;
5361 break;
5362 }
5363
5364 /* Flags */
5365 sz_strlcpy(pnation->flag_graphic_str,
5366 secfile_lookup_str_default(file, "-", "%s.flag", sec_name));
5367 sz_strlcpy(pnation->flag_graphic_alt,
5369 "%s.flag_alt", sec_name));
5370
5371 /* Ruler titles */
5372 for (j = 0;; j++) {
5373 const char *male, *female;
5374
5376 "%s.ruler_titles%d.government",
5377 sec_name, j);
5378 if (NULL == name) {
5379 /* End of the list of ruler titles. */
5380 break;
5381 }
5382
5383 /* NB: even if the government doesn't exist, we load the entries for
5384 * the ruler titles to avoid warnings about unused entries. */
5385 male = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
5386 sec_name, j);
5387 female = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
5388 sec_name, j);
5390
5391 /* Nationset may have been devised with a specific set of govs in
5392 * mind which don't quite match this ruleset, in which case we
5393 * (a) quietly ignore any govs mentioned that don't happen to be in
5394 * the current ruleset, (b) enforce that govs mentioned by nations
5395 * must be on the list */
5396 if (gov != NULL && game.server.ruledit.allowed_govs != NULL) {
5400 /* Gov exists, but not intended for these nations */
5401 gov = NULL;
5403 "Nation %s: government \"%s\" not in allowed_govs.",
5404 nation_rule_name(pnation), name);
5405 ok = FALSE;
5406 break;
5407 }
5408 } else if (!gov) {
5409 /* Gov doesn't exist; only complain if it's not on any list */
5415 "Nation %s: government \"%s\" not found.",
5416 nation_rule_name(pnation), name);
5417 ok = FALSE;
5418 break;
5419 }
5420 }
5421 if (NULL != male && NULL != female) {
5422 if (gov) {
5423 (void) government_ruler_title_new(gov, pnation, male, female);
5424 }
5425 } else {
5427 ok = FALSE;
5428 break;
5429 }
5430 }
5431 if (!ok) {
5432 break;
5433 }
5434
5435 /* City styles */
5436 name = secfile_lookup_str(file, "%s.style", sec_name);
5437 if (!name) {
5439 ok = FALSE;
5440 break;
5441 }
5442 pnation->style = style_by_rule_name(name);
5443 if (pnation->style == NULL) {
5449 "Nation %s: Illegal style \"%s\"",
5450 nation_rule_name(pnation), name);
5451 ok = FALSE;
5452 break;
5453 } else {
5454 log_verbose("Nation %s: style \"%s\" not supported in this "
5455 "ruleset; using default.",
5456 nation_rule_name(pnation), name);
5457 pnation->style = style_by_number(0);
5458 }
5459 }
5460
5461 /* Civilwar nations */
5462 vec = secfile_lookup_str_vec(file, &dim,
5463 "%s.civilwar_nations", sec_name);
5464 for (j = 0; j < dim; j++) {
5466
5467 /* No test for duplicate nations is performed. If there is a duplicate
5468 * entry it will just cause that nation to have an increased
5469 * probability of being chosen. */
5470 if (pconflict == pnation) {
5472 "Nation %s is its own civil war nation",
5473 nation_rule_name(pnation));
5474 ok = FALSE;
5475 break;
5476 } else if (NULL != pconflict) {
5477 nation_list_append(pnation->server.civilwar_nations, pconflict);
5478 nation_list_append(pconflict->server.parent_nations, pnation);
5479 } else {
5480 /* For nation authors, this would probably be considered an error.
5481 * But it can happen normally. The civ1 compatibility ruleset only
5482 * uses the nations that were in civ1, so not all of the links will
5483 * exist. */
5484 log_verbose("Nation %s: civil war nation \"%s\" is unknown.",
5485 nation_rule_name(pnation), vec[j]);
5486 }
5487 }
5488 if (NULL != vec) {
5489 free(vec);
5490 }
5491 if (!ok) {
5492 break;
5493 }
5494
5495 /* Load nation specific initial items */
5496 if (!lookup_tech_list(file, sec_name, "init_techs",
5497 pnation->init_techs, filename)) {
5498 ok = FALSE;
5499 break;
5500 }
5501 if (!lookup_building_list(file, sec_name, "init_buildings",
5502 pnation->init_buildings, filename)) {
5503 ok = FALSE;
5504 break;
5505 }
5506 if (!lookup_unit_list(file, sec_name, "init_units",
5507 pnation->init_units, filename)) {
5508 ok = FALSE;
5509 break;
5510 }
5511 fc_strlcat(tmp, sec_name, 200);
5512 fc_strlcat(tmp, ".init_government", 200);
5513 if (secfile_entry_by_path(file, tmp)) {
5514 pnation->init_government = lookup_government(file, tmp, filename,
5515 NULL);
5516 /* If specified, init_government has to be in this specific ruleset,
5517 * not just allowed_govs */
5518 if (pnation->init_government == NULL) {
5519 ok = FALSE;
5520 break;
5521 }
5522 /* ...but if a list of govs has been specified, enforce that this
5523 * nation's init_government is on the list. */
5525 && !is_on_allowed_list(government_rule_name(pnation->init_government),
5529 "Nation %s: init_government \"%s\" not allowed.",
5530 nation_rule_name(pnation),
5531 government_rule_name(pnation->init_government));
5532 ok = FALSE;
5533 break;
5534 }
5535 }
5536
5537 /* Read default city names. */
5538 if (!load_city_name_list(file, pnation, sec_name, "cities",
5541 ok = FALSE;
5542 break;
5543 }
5544
5545 legend = secfile_lookup_str_default(file, "", "%s.legend", sec_name);
5546 pnation->legend = fc_strdup(legend);
5547 if (check_strlen(pnation->legend, MAX_LEN_MSG, NULL)) {
5549 "Nation %s: legend \"%s\" is too long.",
5550 nation_rule_name(pnation),
5551 pnation->legend);
5552 ok = FALSE;
5553 break;
5554 }
5555
5556 pnation->player = NULL;
5559 sec = NULL;
5560 }
5561
5562 /* Clean up on aborted load */
5563 if (sec != NULL) {
5564 fc_assert(!ok);
5566 }
5567
5568 if (ok) {
5570 }
5571
5572 if (ok) {
5573 /* Update cached number of playable nations in the current set */
5575
5576 /* Sanity checks on all sets */
5579
5580 nations_iterate(pnation) {
5581 if (nation_is_in_set(pnation, pset)) {
5582 switch (nation_barbarian_type(pnation)) {
5583 case NOT_A_BARBARIAN:
5584 if (is_nation_playable(pnation)) {
5585 num_playable++;
5586 }
5587 break;
5588 case LAND_BARBARIAN:
5590 break;
5591 case SEA_BARBARIAN:
5593 break;
5594 case ANIMAL_BARBARIAN:
5595 /* Animals are optional */
5596 break;
5599 break;
5600 default:
5602 }
5603 }
5605 if (num_playable < 1) {
5607 "Nation set \"%s\" has no playable nations. "
5608 "At least one required!", nation_set_rule_name(pset));
5609 ok = FALSE;
5610 break;
5611 }
5612 if (barb_land_count == 0 && barb_both_count == 0) {
5614 "No land barbarian nation defined in set \"%s\". "
5615 "At least one required!", nation_set_rule_name(pset));
5616 ok = FALSE;
5617 break;
5618 }
5619 if (barb_sea_count == 0 && barb_both_count == 0) {
5621 "No sea barbarian nation defined in set \"%s\". "
5622 "At least one required!", nation_set_rule_name(pset));
5623 ok = FALSE;
5624 break;
5625 }
5627 }
5628
5629 return ok;
5630}
5631
5632/**********************************************************************/
5636static bool load_style_names(struct section_file *file,
5637 struct rscompat_info *compat)
5638{
5639 bool ok = TRUE;
5640 struct section_list *sec;
5641 const char *filename = secfile_name(file);
5642
5643 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5644 return FALSE;
5645 }
5646
5647 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5648 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5649
5651 if (NULL == sec) {
5653 "No available nation styles in this ruleset!");
5654 ok = FALSE;
5655 } else {
5657
5659
5661 const int i = style_index(ps);
5662 const char *sec_name = section_name(section_list_get(sec, i));
5663
5664 ruleset_load_names(&ps->name, NULL, file, sec_name);
5666 }
5667
5669
5670 if (ok) {
5671 /* The citystyle sections: */
5672 int i = 0;
5673
5675 if (NULL != sec) {
5677 section_list_iterate(sec, style) {
5678 if (!ruleset_load_names(&city_styles[i].name, NULL, file, section_name(style))) {
5679 ok = FALSE;
5680 break;
5681 }
5682 i++;
5684
5686 } else {
5688 }
5689 }
5690
5691 return ok;
5692}
5693
5694/**********************************************************************/
5697static bool load_ruleset_styles(struct section_file *file,
5698 struct rscompat_info *compat)
5699{
5700 struct section_list *sec;
5701 int i;
5702 bool ok = TRUE;
5703
5704 /* City Styles ... */
5705
5707
5708 /* Get rest: */
5709 for (i = 0; i < game.control.num_city_styles; i++) {
5710 struct requirement_vector *reqs;
5711 const char *sec_name = section_name(section_list_get(sec, i));
5712
5713 sz_strlcpy(city_styles[i].graphic,
5714 secfile_lookup_str(file, "%s.graphic", sec_name));
5715 sz_strlcpy(city_styles[i].graphic_alt,
5716 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
5717 sz_strlcpy(city_styles[i].citizens_graphic,
5719 "%s.citizens_graphic", sec_name));
5720
5722 if (reqs == NULL) {
5723 ok = FALSE;
5724 break;
5725 }
5727 }
5728
5730
5731 if (ok) {
5733
5734 if (sec != NULL) {
5735 int musi;
5736
5739 musi = 0;
5740
5741 section_list_iterate(sec, psection) {
5742 struct requirement_vector *reqs;
5744 const char *sec_name = section_name(psection);
5745
5746 sz_strlcpy(pmus->music_peaceful,
5748 "%s.music_peaceful", sec_name));
5749 sz_strlcpy(pmus->music_combat,
5751 "%s.music_combat", sec_name));
5752
5753 reqs = lookup_req_list(file, compat, sec_name, "reqs", "Music Style");
5754 if (reqs == NULL) {
5755 ok = FALSE;
5756 break;
5757 }
5759
5760 musi++;
5762 }
5763
5765 }
5766
5767 return ok;
5768}
5769
5770/**********************************************************************/
5777 const char *uflags_path,
5778 const char *filename)
5779{
5780 /* Add each listed protected unit type flag as a !present
5781 * requirement. */
5782 if (secfile_entry_lookup(file, "%s", uflags_path)) {
5784 size_t psize;
5785 int i;
5786
5789 "%s", uflags_path);
5790
5791 if (!protecor_flag) {
5792 /* Entity exists but couldn't read it. */
5794 "\"%s\": %s: bad unit type flag list.",
5795 filename, uflags_path);
5796
5797 return FALSE;
5798 }
5799
5800 for (i = 0; i < psize; i++) {
5804 FALSE, FALSE, TRUE,
5805 protecor_flag[i]));
5806 }
5807
5809 }
5810
5811 return TRUE;
5812}
5813
5814/**********************************************************************/
5820 const char *actions_path,
5821 const char *filename)
5822{
5823 /* Read the alternative actions. */
5824 if (secfile_entry_lookup(file, "%s", actions_path)) {
5825 enum gen_action *unit_acts;
5826 size_t asize;
5827 int i;
5828
5830 "%s", actions_path);
5831
5832 if (!unit_acts) {
5833 /* Entity exists but couldn't read it. */
5835 "\"%s\": %s: bad action list",
5836 filename, actions_path);
5837
5838 return FALSE;
5839 }
5840
5841 for (i = 0; i < asize; i++) {
5842 auto_perf->alternatives[i] = unit_acts[i];
5843 }
5844
5845 free(unit_acts);
5846 }
5847
5848 return TRUE;
5849}
5850
5851/**********************************************************************/
5856 const char *item,
5857 const char *filename)
5858{
5859 char uflags_path[100];
5860 char action_path[100];
5861
5863 "missing_unit_upkeep.%s_protected", item);
5865 "missing_unit_upkeep.%s_unit_act", item);
5866
5868 filename)
5870 filename));
5871}
5872
5873/**********************************************************************/
5876static bool load_ruleset_cities(struct section_file *file,
5877 struct rscompat_info *compat)
5878{
5879 const char *filename = secfile_name(file);
5880 const char *item;
5881 struct section_list *sec;
5882 bool ok = TRUE;
5883
5884 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5885 return FALSE;
5886 }
5887
5888 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5889 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5890
5891 /* Specialist options */
5893 if (!sec) {
5894 ruleset_error(NULL, LOG_ERROR, "\"%s\": No specialists.", filename);
5895 ok = FALSE;
5896 } else if (section_list_size(sec) >= SP_MAX) {
5898 "\"%s\": Too many specialists (%d, max %d).",
5899 filename, section_list_size(sec), SP_MAX);
5900 ok = FALSE;
5901 }
5902
5903 if (ok) {
5904 int i = 0;
5905 const char *tag;
5906
5908
5909 section_list_iterate(sec, psection) {
5910 struct specialist *s = specialist_by_number(i);
5911 struct requirement_vector *reqs;
5912 const char *sec_name = section_name(psection);
5913
5914 if (!ruleset_load_names(&s->name, NULL, file, sec_name)) {
5915 ok = FALSE;
5916 break;
5917 }
5918
5920 "%s.short_name", sec_name);
5922
5923 tag = secfile_lookup_str(file, "%s.graphic", sec_name);
5924 if (tag == NULL) {
5926 "\"%s\": No graphic tag for specialist at %s.",
5927 filename, sec_name);
5928 ok = FALSE;
5929 break;
5930 }
5931 sz_strlcpy(s->graphic_str, tag);
5934 "%s.graphic_alt", sec_name));
5935
5937 if (reqs == NULL) {
5938 ok = FALSE;
5939 break;
5940 }
5942
5943 s->helptext = lookup_strvec(file, sec_name, "helptext");
5944
5945 if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
5947 }
5948 i++;
5950 }
5951
5952 if (ok && DEFAULT_SPECIALIST == -1) {
5954 "\"%s\": must have zero reqs for at least one "
5955 "specialist type.", filename);
5956 ok = FALSE;
5957 }
5959 sec = NULL;
5960
5961 if (ok) {
5962 /* City Parameters */
5963
5966 "parameters.celebrate_size_limit");
5968 secfile_lookup_int_default(file, GAME_DEFAULT_ADDTOSIZE, "parameters.add_to_size_limit");
5971 "parameters.angry_citizens");
5972
5974 secfile_lookup_bool_default(file, GAME_DEFAULT_CHANGABLE_TAX, "parameters.changable_tax");
5976 secfile_lookup_int_default(file, 0, "parameters.forced_science");
5978 secfile_lookup_int_default(file, 100, "parameters.forced_luxury");
5980 secfile_lookup_int_default(file, 0, "parameters.forced_gold");
5982 + game.info.forced_gold != 100) {
5984 "\"%s\": Forced taxes do not add up in ruleset!",
5985 filename);
5986 ok = FALSE;
5987 }
5988 }
5989
5990 if (ok) {
5991 /* civ1 & 2 didn't reveal tiles */
5994 "parameters.vision_reveal_tiles");
5995
5997 secfile_lookup_int_default(file, 1, "parameters.pop_report_zeroes");
5998
5999 /* Citizens configuration. */
6002 "citizen.nationality");
6005 "citizen.ubuilder_nationality");
6008 "citizen.convert_speed");
6010 secfile_lookup_int_default(file, 0, "citizen.partisans_pct");
6012 secfile_lookup_int_default(file, 0, "citizen.conquest_convert_pct");
6013 }
6014
6015 if (ok) {
6016 /* Missing unit upkeep. */
6018
6019 /* Can't pay food upkeep! */
6021 auto_perf->cause = AAPC_UNIT_UPKEEP;
6022
6023 /* This is about food upkeep. */
6025 req_from_str("OutputType", "Local",
6026 FALSE, TRUE, TRUE,
6027 "Food"));
6028
6029 /* Internally represented as an action auto performer rule. */
6030 if (!load_muuk_as_action_auto(file, auto_perf, "food", filename)) {
6031 ok = FALSE;
6032 }
6033
6036 "missing_unit_upkeep.food_wipe");
6037
6038 /* Can't pay gold upkeep! */
6040 auto_perf->cause = AAPC_UNIT_UPKEEP;
6041
6042 /* This is about gold upkeep. */
6044 req_from_str("OutputType", "Local",
6045 FALSE, TRUE, TRUE,
6046 "Gold"));
6047
6048 /* Internally represented as an action auto performer rule. */
6049 if (!load_muuk_as_action_auto(file, auto_perf, "gold", filename)) {
6050 ok = FALSE;
6051 }
6052
6055 "missing_unit_upkeep.gold_wipe");
6056
6057 /* Can't pay shield upkeep! */
6059 auto_perf->cause = AAPC_UNIT_UPKEEP;
6060
6061 /* This is about shield upkeep. */
6063 req_from_str("OutputType", "Local",
6064 FALSE, TRUE, TRUE,
6065 "Shield"));
6066
6067 /* Internally represented as an action auto performer rule. */
6068 if (!load_muuk_as_action_auto(file, auto_perf, "shield", filename)) {
6069 ok = FALSE;
6070 }
6071
6074 "missing_unit_upkeep.shield_wipe");
6075 }
6076
6077 if (ok) {
6079 }
6080
6081 return ok;
6082}
6083
6084/**********************************************************************/
6087static bool load_ruleset_effects(struct section_file *file,
6088 struct rscompat_info *compat)
6089{
6090 struct section_list *sec;
6091 const char *filename;
6092 bool ok = TRUE;
6093
6094 filename = secfile_name(file);
6095
6096 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6097 return FALSE;
6098 }
6099
6100 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6101 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6102
6104
6105 if (sec != NULL) {
6106 section_list_iterate(sec, psection) {
6107 const char *sec_name = section_name(psection);
6108 enum effect_type main_type;
6109 enum effect_type ai_valued_as;
6110 const char *type;
6111
6112 type = secfile_lookup_str(file, "%s.type", sec_name);
6113 if (type == NULL) {
6115 "\"%s\" [%s] missing effect type.",
6116 filename, sec_name);
6117 ok = FALSE;
6118 break;
6119 }
6123 "\"%s\" [%s] lists unknown effect type \"%s\".",
6124 filename, sec_name, type);
6125 ok = FALSE;
6126 break;
6127 }
6128 if (!is_user_effect(main_type)) {
6130 "\"%s\" [%s] type \"%s\" is not an user effect.",
6131 filename, sec_name, type);
6132 ok = FALSE;
6133 break;
6134 }
6135
6136 type = secfile_lookup_str(file, "%s.ai_valued_as", sec_name);
6137 if (type == NULL) {
6139 "\"%s\" [%s] missing ai_valued_as.",
6140 filename, sec_name);
6141 ok = FALSE;
6142 break;
6143 }
6147 "\"%s\" [%s] lists unknown ai_valued_as \"%s\".",
6148 filename, sec_name, type);
6149 ok = FALSE;
6150 break;
6151 }
6154 "\"%s\" [%s] ai_valued_as \"%s\" is an user effect.",
6155 filename, sec_name, type);
6156 ok = FALSE;
6157 break;
6158 }
6159
6161 /* It has been set already! */
6163 "\"%s\" [%s] Duplicate \"%s\" entry.",
6164 filename, sec_name, type);
6165 ok = FALSE;
6166 break;
6167 }
6168
6171
6173 }
6174
6175 /* Parse effects and add them to the effects ruleset cache. */
6177 section_list_iterate(sec, psection) {
6178 enum effect_type eff;
6179 int value;
6180 struct multiplier *pmul;
6181 struct effect *peffect;
6182 const char *sec_name = section_name(psection);
6183 struct requirement_vector *reqs;
6184 const char *type;
6185 const char *comment;
6186
6187 type = secfile_lookup_str(file, "%s.type", sec_name);
6188
6189 if (type == NULL) {
6191 "\"%s\" [%s] missing effect type.",
6192 filename, sec_name);
6193 ok = FALSE;
6194 break;
6195 }
6196
6197 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
6199 }
6200
6202 if (!effect_type_is_valid(eff)) {
6204 "\"%s\" [%s] lists unknown effect type \"%s\".",
6205 filename, sec_name, type);
6206 ok = FALSE;
6207 break;
6208 }
6209
6210 value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
6211
6212 {
6213 const char *multiplier_name
6214 = secfile_lookup_str(file, "%s.multiplier", sec_name);
6215
6216 if (multiplier_name) {
6218 if (!pmul) {
6220 "\"%s\" [%s] has unknown multiplier \"%s\".",
6221 filename, sec_name, multiplier_name);
6222 ok = FALSE;
6223 break;
6224 }
6225 } else {
6226 pmul = NULL;
6227 }
6228 }
6229
6230 peffect = effect_new(eff, value, pmul);
6231
6232 reqs = lookup_req_list(file, compat, sec_name, "reqs", type);
6233 if (reqs == NULL) {
6234 ok = FALSE;
6235 break;
6236 }
6237
6241
6242 comment = secfile_lookup_str_default(file, NULL, "%s.comment", sec_name);
6243
6244 if (comment != NULL) {
6245 peffect->rulesave.comment = fc_strdup(comment);
6246 }
6247
6250
6251 if (ok) {
6253 }
6254
6255 return ok;
6256}
6257
6258/**********************************************************************/
6262 int def, int min, int max,
6263 const char *path, ...)
6264{
6265 char fullpath[256];
6266 int ival;
6267 va_list args;
6268
6269 va_start(args, path);
6270 fc_vsnprintf(fullpath, sizeof(fullpath), path, args);
6271 va_end(args);
6272
6273 if (!secfile_lookup_int(file, &ival, "%s", fullpath)) {
6274 ival = def;
6275 }
6276
6277 if (ival < min) {
6279 "\"%s\" should be in the interval [%d, %d] "
6280 "but is %d; using the minimal value.",
6281 fullpath, min, max, ival);
6282 ival = min;
6283 }
6284
6285 if (ival > max) {
6287 "\"%s\" should be in the interval [%d, %d] "
6288 "but is %d; using the maximal value.",
6289 fullpath, min, max, ival);
6290 ival = max;
6291 }
6292
6293 return ival;
6294}
6295
6296/**********************************************************************/
6299static bool load_action_range_max(struct section_file *file, action_id act)
6300{
6301 struct action *paction = action_by_number(act);
6302 const char *vname = action_max_range_ruleset_var_name(act);
6303
6304 if (vname != NULL) {
6305 struct entry *pentry;
6306 int max_range;
6307
6308 pentry = secfile_entry_lookup(file, "actions.%s", vname);
6309
6310 if (pentry == NULL) {
6312 } else {
6313 const char *custom;
6314
6317 /* max_range already assigned */
6318 } else if (entry_type_get(pentry) == ENTRY_STR
6322 } else {
6323 ruleset_error(NULL, LOG_ERROR, "Bad actions.%s",
6326
6327 return FALSE;
6328 }
6329 }
6330
6332 }
6333
6334 return TRUE;
6335}
6336
6337/**********************************************************************/
6340static bool load_action_range(struct section_file *file, action_id act)
6341{
6342 struct action *paction = action_by_number(act);
6343 const char *vname;
6344
6345 if (!load_action_range_max(file, act)) {
6346 return FALSE;
6347 }
6348
6350 if (vname != NULL) {
6351 /* Min range can be loaded from the ruleset. */
6355 "actions.%s",
6356 vname);
6357 }
6358
6359 return TRUE;
6360}
6361
6362/**********************************************************************/
6365static bool load_action_kind(struct section_file *file, action_id act)
6366{
6367 struct action *paction = action_by_number(act);
6369
6370 if (var_name != NULL) {
6374 paction->result),
6376 "actions.%s", var_name);
6377 } else {
6380 }
6381
6382 return TRUE;
6383}
6384
6385/**********************************************************************/
6389 action_id act)
6390{
6392 /* Actor consumption can be loaded from the ruleset. */
6395 file, RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS, "actions.%s",
6397 }
6398
6399 return TRUE;
6400}
6401
6402/**********************************************************************/
6406 const char *filename,
6407 struct action *paction,
6408 struct rscompat_info *compat)
6409{
6411
6412 if (var_name != nullptr) {
6413 /* Action blocking can be loaded from the ruleset. */
6414 char fullpath[1024];
6415
6416 fc_snprintf(fullpath, sizeof(fullpath), "actions.%s", var_name);
6417
6418 if (secfile_entry_by_path(file, fullpath)) {
6420 size_t asize;
6421 int j;
6422
6425
6426 if (!blocking_actions) {
6427 /* Entity exists but couldn't read it. */
6429 "\"%s\": %s: bad action list",
6430 filename, fullpath);
6431
6432 return FALSE;
6433 }
6434
6435 for (j = 0; j < asize; j++) {
6436 BV_SET(paction->blocked_by, blocking_actions[j]);
6437 }
6438
6440 } else if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
6442
6443 if (secfile_entry_by_path(file, fullpath)) {
6445 size_t asize;
6446 int j;
6447
6450
6451 if (!blocking_actions) {
6452 /* Entity exists but couldn't read it. */
6454 "\"%s\": %s: bad action list",
6455 filename, fullpath);
6456
6457 return FALSE;
6458 }
6459
6460 for (j = 0; j < asize; j++) {
6461 BV_SET(paction->blocked_by, blocking_actions[j]);
6462 }
6463
6465 }
6466 }
6467 }
6468
6469 return TRUE;
6470}
6471
6472/**********************************************************************/
6477 const char *filename,
6478 int performer_slot,
6479 struct action *paction)
6480{
6482 char action_list_path[100];
6483
6485 /* Not relevant. */
6486 return TRUE;
6487 }
6488
6490 auto_perf->cause = AAPC_POST_ACTION;
6491
6492 /* Limit auto performer to this action. */
6495 FALSE, TRUE, TRUE,
6496 paction->id));
6497
6498 /* Load the list of actions. */
6500 "actions.%s",
6503 action_list_path, filename)) {
6504 return FALSE;
6505 }
6506
6507 return TRUE;
6508}
6509
6510/**********************************************************************/
6513static bool lookup_bv_actions(struct section_file *file,
6514 const char *filename,
6515 bv_actions *target,
6516 const char *path)
6517{
6518 if (secfile_entry_by_path(file, path)) {
6520 size_t asize;
6521 int j;
6522
6524 "%s", path);
6525
6526 if (!listed_actions) {
6527 /* Entity exists but couldn't read it. */
6528 ruleset_error(NULL, LOG_ERROR, "\"%s\": %s: bad action list",
6529 filename, path);
6530
6531 return FALSE;
6532 }
6533
6534 for (j = 0; j < asize; j++) {
6535 BV_SET(*target, listed_actions[j]);
6536 }
6537
6539 }
6540
6541 return TRUE;
6542}
6543
6544/**********************************************************************/
6547static bool load_ruleset_game(struct section_file *file, bool act,
6548 struct rscompat_info *compat)
6549{
6550 const char *sval, **svec;
6551 const char *filename;
6552 int *food_ini;
6553 int i;
6554 size_t teams;
6555 const char *pref_text;
6556 size_t gni_tmp;
6557 struct section_list *sec;
6558 size_t nval;
6559 const char *name;
6560 bool ok = TRUE;
6561
6562 if (file == NULL) {
6563 return FALSE;
6564 }
6565 filename = secfile_name(file);
6566
6567 name = secfile_lookup_str_default(file, NULL, "ruledit.description_file");
6568 if (name != NULL) {
6570 }
6572 = secfile_lookup_bool_default(file, FALSE, "ruledit.std_tileset_compat");
6573
6574 /* Section: tileset */
6575 pref_text = secfile_lookup_str_default(file, "", "tileset.preferred");
6576 if (pref_text[0] != '\0') {
6577 /* There was tileset suggestion */
6579 } else {
6580 /* No tileset suggestions */
6581 game.control.preferred_tileset[0] = '\0';
6582 }
6583
6584 /* Section: soundset */
6585 pref_text = secfile_lookup_str_default(file, "", "soundset.preferred");
6586 if (pref_text[0] != '\0') {
6587 /* There was soundset suggestion */
6589 } else {
6590 /* No soundset suggestions */
6592 }
6593
6594 /* Section: musicset */
6595 pref_text = secfile_lookup_str_default(file, "", "musicset.preferred");
6596 if (pref_text[0] != '\0') {
6597 /* There was musicset suggestion */
6599 } else {
6600 /* No musicset suggestions */
6602 }
6603
6604 /* Section: about */
6605 pref_text = secfile_lookup_str(file, "about.name");
6606 /* Ruleset/modpack name found */
6608
6609 pref_text = secfile_lookup_str_default(file, "", "about.version");
6610 if (pref_text[0] != '\0') {
6611 /* Ruleset/modpack version found */
6613 } else {
6614 /* No version information */
6615 game.control.version[0] = '\0';
6616 }
6617
6618 pref_text = secfile_lookup_str_default(file, "", "about.alt_dir");
6619 if (pref_text[0] != '\0') {
6620 /* Alt directory definition found. */
6622 } else {
6623 /* No alt directory information */
6624 game.control.alt_dir[0] = '\0';
6625 }
6626
6627 pref_text = secfile_lookup_str_default(file, "", "about.summary");
6628 if (pref_text[0] != '\0') {
6629 int len;
6630
6631 /* Ruleset/modpack summary found */
6632 len = strlen(pref_text);
6635 } else {
6636 /* No summary */
6637 if (game.ruleset_summary != NULL) {
6640 }
6641 }
6642
6643 pref_text = secfile_lookup_str_default(file, "", "about.description");
6644 if (pref_text[0] != '\0') {
6645 int len;
6646
6647 /* Ruleset/modpack description found */
6648 len = strlen(pref_text);
6652 } else {
6653 /* No description */
6654 if (game.ruleset_description != NULL) {
6657 }
6659 }
6660
6661 pref_text = secfile_lookup_str_default(file, "", "about.capabilities");
6662 if (pref_text[0] != '\0') {
6663 int len = strlen(pref_text);
6664
6667 } else {
6669 game.ruleset_capabilities[0] = '\0';
6670 }
6671
6672 /* Section: options */
6673 if (!lookup_tech_list(file, "options", "global_init_techs",
6674 game.rgame.global_init_techs, filename)) {
6675 ok = FALSE;
6676 }
6677
6678 if (ok) {
6679 if (!lookup_building_list(file, "options", "global_init_buildings",
6680 game.rgame.global_init_buildings, filename)) {
6681 ok = FALSE;
6682 }
6683 }
6684
6685 if (ok) {
6686 const char **slist;
6687 int j;
6688
6690 "options.popup_tech_help");
6691
6692 /* section: civstyle */
6695 "civstyle.base_pollution");
6696
6698
6699 slist = secfile_lookup_str_vec(file, &nval, "civstyle.gameloss_style");
6700 for (j = 0; j < nval; j++) {
6701 enum gameloss_style style;
6702
6703 sval = slist[j];
6704 if (strcmp(sval, "") == 0) {
6705 continue;
6706 }
6708 if (!gameloss_style_is_valid(style)) {
6710 "\"%s\": bad value \"%s\" for gameloss_style.",
6711 filename, sval);
6712 ok = FALSE;
6713 break;
6714 } else {
6715 game.info.gameloss_style |= style;
6716 }
6717 }
6718 free(slist);
6719 }
6720
6721 if (ok) {
6727 "civstyle.happy_cost");
6733 "civstyle.food_cost");
6734
6735 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
6737 = secfile_lookup_bool_default(file, TRUE, "civstyle.civil_war_enabled");
6739 } else {
6740 /* Avoid additional Civil War enabler */
6742 }
6743
6749 "civstyle.base_bribe_cost");
6755 "civstyle.ransom_gold");
6758 "civstyle.pillage_select");
6759
6762 "civstyle.tech_steal_allow_holes");
6765 "civstyle.tech_trade_allow_holes");
6768 "civstyle.tech_trade_loss_allow_holes");
6771 "civstyle.tech_parasite_allow_holes");
6774 "civstyle.tech_loss_allow_holes");
6775
6781 "civstyle.upgrade_veteran_loss");
6787 "civstyle.autoupgrade_veteran_loss");
6788
6794 "research.base_tech_cost");
6795
6801 "research.min_tech_cost");
6802
6804 "civstyle.granary_food_ini");
6806
6809 "Too many granary_food_ini entries (%d, max %d)",
6811 ok = FALSE;
6812 } else if (game.info.granary_num_inis == 0) {
6813 log_error("No values for granary_food_ini. Using default "
6814 "value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
6817 } else {
6818 int gi;
6819
6820 /* check for <= 0 entries */
6821 for (gi = 0; gi < game.info.granary_num_inis; gi++) {
6822 if (food_ini[gi] <= 0) {
6823 if (gi == 0) {
6825 } else {
6826 food_ini[gi] = food_ini[gi - 1];
6827 }
6828 log_error("Bad value for granary_food_ini[%i]. Using %i.",
6829 gi, food_ini[gi]);
6830 }
6832 }
6833 }
6834 free(food_ini);
6835 }
6836
6837 if (ok) {
6843 "civstyle.granary_food_inc");
6844
6851 "civstyle.min_city_center_%s",
6854 }
6855
6856 if (ok) {
6857 const char *tus_text;
6858
6864 "civstyle.init_vis_radius_sq");
6865
6871 "civstyle.init_city_radius_sq");
6872
6874 "civstyle.gold_upkeep_style");
6879 "Unknown gold upkeep style \"%s\"",
6880 tus_text);
6881 ok = FALSE;
6882 }
6883
6885 = secfile_lookup_bool_default(file, FALSE, "civstyle.homeless_gold_upkeep");
6886
6890 "Cannot have homeless_gold_upkeep while gold_upkeep_style \"City\".");
6891 ok = FALSE;
6892 }
6893
6895 "civstyle.output_granularity");
6896
6898 = secfile_lookup_bool_default(file, FALSE, "civstyle.airlift_from_always_enabled");
6899
6901 = secfile_lookup_bool_default(file, TRUE, "civstyle.airlift_to_always_enabled");
6902
6903 /* section: wonder_visibility */
6904 if (ok) {
6905 const char *text;
6906
6907 text = secfile_lookup_str_default(file,
6909 "wonder_visibility.small_wonders");
6910
6915 "Unknown wonder visibility type \"%s\"",
6916 text);
6917 ok = FALSE;
6918 }
6919 }
6920
6921 /* section: illness */
6924 "illness.illness_on");
6930 "illness.illness_base_factor");
6936 "illness.illness_min_size");
6942 "illness.illness_trade_infection");
6948 "illness.illness_pollution_factor");
6949
6950 /* section: incite_cost */
6956 "incite_cost.base_incite_cost");
6962 "incite_cost.improvement_factor");
6968 "incite_cost.unit_factor");
6974 "incite_cost.total_factor");
6975 }
6976
6977 if (ok) {
6978 const char *tus_text;
6979 int pharbor_default;
6980
6981 /* Section: combat_rules */
6984 "combat_rules.tired_attack");
6985
6988 "combat_rules.only_killing_makes_veteran");
6989
6992 "combat_rules.only_real_fight_makes_veteran");
6993
6996 "combat_rules.combat_odds_scaled_veterancy");
6997
7000 "combat_rules.damage_reduces_bombard_rate");
7001
7004 "combat_rules.low_firepower_badwallattacker");
7005
7006 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
7009 "combat_rules.low_firepower_pearl_harbour");
7010 } else {
7011 pharbor_default = 1;
7012 }
7013
7016 "combat_rules.low_firepower_pearl_harbor");
7017
7020 "combat_rules.low_firepower_combat_bonus");
7023 "combat_rules.low_firepower_nonnat_bombard");
7024
7029 "combat_rules.nuke_pop_loss_pct");
7030
7035 "combat_rules.nuke_defender_survival_chance_pct");
7036
7037 /* section: borders */
7043 "borders.radius_sq_city");
7049 "borders.size_effect");
7050
7056 "borders.radius_sq_city_permanent");
7057
7058 /* section: research */
7060 "research.tech_cost_style");
7065 "Unknown tech cost style \"%s\"",
7066 tus_text);
7067 ok = FALSE;
7068 }
7069
7071 "research.tech_leakage");
7076 "Unknown tech leakage \"%s\"",
7077 tus_text);
7078 ok = FALSE;
7079 }
7082 log_error("Only tech_leakage \"%s\" supported with "
7083 "tech_cost_style \"%s\". ",
7086 log_error("Switching to tech_leakage \"%s\".",
7089 }
7095 "research.base_tech_cost");
7096
7098 "research.tech_upkeep_style");
7099
7101
7104 "Unknown tech upkeep style \"%s\"",
7105 tus_text);
7106 ok = FALSE;
7107 }
7108 }
7109
7110 if (ok) {
7116 "research.tech_upkeep_divider");
7117
7118 sval = secfile_lookup_str_default(file, NULL, "research.free_tech_method");
7119 if (sval == NULL) {
7121 "No free_tech_method given");
7122 ok = FALSE;
7123 } else {
7127 "Bad value %s for free_tech_method.", sval);
7128 ok = FALSE;
7129 }
7130 }
7131 }
7132
7133 if (ok) {
7134 int cf;
7135
7136 /* section: culture */
7139 "culture.victory_min_points");
7142 "culture.victory_lead_pct");
7145 "culture.migration_pml");
7148 "culture.history_interest_pml");
7149
7150 /* section: world_peace */
7153 "world_peace.victory_turns");
7154
7155 /* section: calendar */
7158 "calendar.skip_year_0");
7161 "calendar.start_year");
7163 = secfile_lookup_int_default(file, 0, "calendar.fragments");
7164
7167 "Too many calendar fragments. Max is %d",
7169 ok = FALSE;
7171 }
7175 "calendar.positive_label"));
7179 "calendar.negative_label"));
7180
7181 for (cf = 0; cf < game.calendar.calendar_fragments; cf++) {
7182 const char *fname;
7183
7184 fname = secfile_lookup_str_default(file, NULL, "calendar.fragment_name%d", cf);
7185 if (fname != NULL) {
7188 }
7189 }
7190 }
7191
7192 if (ok) {
7193 /* section playercolors */
7194 struct rgbcolor *prgbcolor = NULL;
7195 bool color_read = TRUE;
7196
7197 /* Check if the player list is defined and empty. */
7198 if (playercolor_count() != 0) {
7199 ok = FALSE;
7200 } else {
7201 i = 0;
7202
7203 while (color_read) {
7204 prgbcolor = NULL;
7205
7206 color_read = rgbcolor_load(file, &prgbcolor, "playercolors.colorlist%d", i);
7207 if (color_read) {
7209 }
7210
7211 i++;
7212 }
7213
7214 if (playercolor_count() == 0) {
7215 ruleset_error(NULL, LOG_ERROR, "No player colors defined!");
7216 ok = FALSE;
7217 }
7218
7219 if (ok) {
7221 if (!rgbcolor_load(file, &game.plr_bg_color, "playercolors.background")) {
7223 "No background player color defined! (%s)",
7224 secfile_error());
7225 ok = FALSE;
7226 }
7227 }
7228 }
7229 }
7230
7231 if (ok) {
7232 /* section: teams */
7233 svec = secfile_lookup_str_vec(file, &teams, "teams.names");
7234 if (team_slot_count() < teams) {
7236 }
7238 for (i = 0; i < teams; i++) {
7240 }
7241 free(svec);
7242
7244 nval = (NULL != sec ? section_list_size(sec) : 0);
7245 if (nval > MAX_DISASTER_TYPES) {
7246 int num = nval; /* No "size_t" to printf */
7247
7249 "\"%s\": Too many disaster types (%d, max %d)",
7250 filename, num, MAX_DISASTER_TYPES);
7252 ok = FALSE;
7253 } else {
7255 }
7256 }
7257
7258 if (ok) {
7260 int id = disaster_index(pdis);
7261 int j;
7262 size_t eff_count;
7263 struct requirement_vector *reqs;
7264 const char *sec_name = section_name(section_list_get(sec, id));
7265
7266 if (!ruleset_load_names(&pdis->name, NULL, file, sec_name)) {
7268 "\"%s\": Cannot load disaster names",
7269 filename);
7270 ok = FALSE;
7271 break;
7272 }
7273
7275 if (reqs == NULL) {
7276 ok = FALSE;
7277 break;
7278 }
7280
7282 "%s.frequency", sec_name);
7283
7284 svec = secfile_lookup_str_vec(file, &eff_count, "%s.effects", sec_name);
7285
7286 BV_CLR_ALL(pdis->effects);
7287 for (j = 0; j < eff_count; j++) {
7288 const char *dsval = svec[j];
7290
7292
7295 "\"%s\" disaster \"%s\": unknown effect \"%s\".",
7296 filename, disaster_rule_name(pdis), dsval);
7297 ok = FALSE;
7298 break;
7299 } else {
7300 BV_SET(pdis->effects, effect);
7301 }
7302 }
7303
7304 free(svec);
7305
7306 if (!ok) {
7307 break;
7308 }
7311 }
7312
7313 if (ok) {
7315
7317 int id = achievement_index(pach);
7318 const char *sec_name = section_name(section_list_get(sec, id));
7319 const char *typename;
7320 const char *msg;
7321
7322 typename = secfile_lookup_str_default(file, NULL, "%s.type", sec_name);
7323
7324 pach->type = achievement_type_by_name(typename, fc_strcasecmp);
7325 if (!achievement_type_is_valid(pach->type)) {
7327 "Achievement has unknown type \"%s\".",
7328 typename != NULL ? typename : "(NULL)");
7329 ok = FALSE;
7330 }
7331
7332 if (ok) {
7334 "%s.unique", sec_name);
7335
7337 "%s.value", sec_name);
7338 pach->culture = secfile_lookup_int_default(file, 0,
7339 "%s.culture", sec_name);
7340
7341 msg = secfile_lookup_str_default(file, NULL, "%s.first_msg", sec_name);
7342 if (msg == NULL) {
7344 "Achievement %s has no first msg!", sec_name);
7345 ok = FALSE;
7346 } else {
7347 pach->first_msg = fc_strdup(msg);
7348 }
7349 }
7350
7351 if (ok) {
7352 msg = secfile_lookup_str_default(file, NULL, "%s.cons_msg", sec_name);
7353 if (msg == NULL) {
7354 if (!pach->unique) {
7356 "Achievement %s has no msg for consecutive gainers!",
7357 sec_name);
7358 ok = FALSE;
7359 }
7360 } else {
7361 pach->cons_msg = fc_strdup(msg);
7362 }
7363 }
7364
7365 if (!ok) {
7366 break;
7367 }
7370 }
7371
7372 if (ok) {
7373 for (i = 0; (name = secfile_lookup_str_default(file, NULL,
7374 "trade.settings%d.type",
7375 i)); i++) {
7377
7378 if (type == TRT_LAST) {
7380 "\"%s\" unknown trade route type \"%s\".",
7381 filename, name);
7382 ok = FALSE;
7383 } else {
7385 const char *cancelling;
7386 const char *bonus;
7387
7388 set->trade_pct = secfile_lookup_int_default(file, 100,
7389 "trade.settings%d.pct", i);
7390 cancelling = secfile_lookup_str_default(file, "Active",
7391 "trade.settings%d.cancelling", i);
7393 if (set->cancelling == TRI_LAST) {
7395 "\"%s\" unknown trade route cancelling type \"%s\".",
7396 filename, cancelling);
7397 ok = FALSE;
7398 }
7399
7400 bonus = secfile_lookup_str_default(file, "None", "trade.settings%d.bonus", i);
7401
7403
7406 "\"%s\" unknown trade route bonus type \"%s\".",
7407 filename, bonus);
7408 ok = FALSE;
7409 }
7410 }
7411 }
7412 }
7413
7414 if (ok) {
7415 const char *str;
7416
7418 = secfile_lookup_int_default(file, 0, "trade.min_trade_route_val");
7419
7422 "trade.reveal_trade_partner");
7423
7426 "trade.goods_selection");
7427
7429
7432 "\"%s\" goods selection method \"%s\" unknown.",
7433 filename, str);
7434 ok = FALSE;
7435 }
7436 }
7437
7438 if (ok) {
7440
7442 int id = goods_index(pgood);
7443 const char *sec_name = section_name(section_list_get(sec, id));
7444 struct requirement_vector *reqs;
7445 const char **slist;
7446 int j;
7447
7449 if (reqs == NULL) {
7450 ok = FALSE;
7451 break;
7452 }
7454
7455 pgood->from_pct = secfile_lookup_int_default(file, 100,
7456 "%s.from_pct", sec_name);
7457 pgood->to_pct = secfile_lookup_int_default(file, 100,
7458 "%s.to_pct", sec_name);
7459 pgood->onetime_pct = secfile_lookup_int_default(file, 100,
7460 "%s.onetime_pct", sec_name);
7461 pgood->select_priority = secfile_lookup_int_default(file, 1,
7462 "%s.select_priority", sec_name);
7463 pgood->replace_priority = secfile_lookup_int_default(file, 1,
7464 "%s.replace_priority", sec_name);
7465
7466 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
7467 BV_CLR_ALL(pgood->flags);
7468 for (j = 0; j < nval; j++) {
7469 enum goods_flag_id flag;
7470
7471 sval = slist[j];
7473 if (!goods_flag_id_is_valid(flag)) {
7474 ruleset_error(NULL, LOG_ERROR, "\"%s\" good \"%s\": unknown flag \"%s\".",
7475 filename, goods_rule_name(pgood), sval);
7476 ok = FALSE;
7477 break;
7478 } else {
7479 BV_SET(pgood->flags, flag);
7480 }
7481 }
7482 free(slist);
7483
7484 pgood->helptext = lookup_strvec(file, sec_name, "helptext");
7487 }
7488
7489 if (ok) {
7491
7492 if (sec != NULL) {
7493 int num = section_list_size(sec);
7494
7495 for (i = 0; i < num; i++) {
7496 const char *sec_name = section_name(section_list_get(sec, i));
7497 const char *clause_name = secfile_lookup_str_default(file, NULL,
7498 "%s.type", sec_name);
7500 struct clause_info *info;
7501 struct requirement_vector *reqs;
7502
7503 if (!clause_type_is_valid(type)) {
7505 "\"%s\" unknown clause type \"%s\".",
7506 filename, clause_name);
7507 ok = FALSE;
7508 break;
7509 }
7510
7511 info = clause_info_get(type);
7512
7513 if (info->enabled) {
7515 "\"%s\" duplicate clause type \"%s\" definition.",
7516 filename, clause_name);
7517 ok = FALSE;
7518 break;
7519 }
7520
7521 reqs = lookup_req_list(file, compat, sec_name, "giver_reqs", clause_name);
7522 if (reqs == NULL) {
7523 ok = FALSE;
7524 break;
7525 }
7527
7528 reqs = lookup_req_list(file, compat, sec_name, "receiver_reqs", clause_name);
7529 if (reqs == NULL) {
7530 ok = FALSE;
7531 break;
7532 }
7534
7535 reqs = lookup_req_list(file, compat, sec_name, "either_reqs", clause_name);
7536 if (reqs == NULL) {
7537 ok = FALSE;
7538 break;
7539 }
7541
7542 info->enabled = TRUE;
7543 }
7544 }
7546 }
7547
7548 if (ok) {
7550
7551 if (sec != NULL) {
7552 int num = section_list_size(sec);
7553 int curr;
7554
7555 for (curr = 0; curr < num; curr++) {
7556
7557 struct counter *pcount = counter_by_id(curr);
7558 const char *sec_name = section_name(section_list_get(sec, curr));
7559 const char *counter_type = secfile_lookup_str_default(file, NULL,
7560 "%s.type",
7561 sec_name);
7562
7565 if (!counter_behavior_is_valid(cb)) {
7567 "\"%s\" unknown counter type \"%s\".",
7568 filename, counter_type);
7569 ok = FALSE;
7570 break;
7571 }
7572
7573 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
7575 "\"%s\": Cannot load counter names",
7576 filename);
7577 ok = FALSE;
7578 break;
7579 }
7580
7581 pcount->helptext = lookup_strvec(file, sec_name, "helptext");
7582 pcount->type = cb;
7583 if (!secfile_lookup_int(file, &pcount->checkpoint,
7584 "%s.checkpoint", sec_name)) {
7585
7587 "\"%s\": No checkpoint value",
7588 filename);
7589 ok = FALSE;
7590 break;
7591 }
7592
7593 pcount->target = CTGT_CITY;
7594 pcount->index = curr;
7595 pcount->def = secfile_lookup_int_default(file, 0,
7596 "%s.def",
7597 sec_name);
7599 }
7600 }
7601 }
7602
7603 /* secfile_check_unused() is not here, but only after also settings section
7604 * has been loaded. */
7605
7606 return ok;
7607}
7608
7609/**********************************************************************/
7612static bool load_ruleset_actions(struct section_file *file,
7613 struct section_file *gamefile,
7614 struct rscompat_info *compat)
7615{
7616 bool ok = TRUE;
7617 const char *filename = secfile_name(file);
7618 struct section_list *sec;
7620 struct requirement_vector *reqs;
7621
7622 /* Auto attack. */
7623
7624 /* Action auto performers aren't ready to be exposed in the ruleset
7625 * yet. The behavior when two action auto performers for the same
7626 * cause can fire isn't set in stone yet. How is one of them chosen?
7627 * What if all the actions of the chosen action auto performer turned
7628 * out to be illegal but one of the other action auto performers that
7629 * fired has legal actions? These issues can decide what other action
7630 * rules action auto performers can represent in the future. Deciding
7631 * should therefore wait until a rule needs action auto performers to
7632 * work a certain way. */
7633 /* Only one action auto performer, ACTION_AUTO_MOVED_ADJ, is caused
7634 * by AAPC_UNIT_MOVED_ADJ. It is therefore safe to expose the full
7635 * requirement vector to the ruleset. */
7636
7637 /* A unit moved next to this unit and the autoattack server setting
7638 * is enabled. */
7641
7642 reqs = lookup_req_list(file, compat,
7643 "auto_attack", "if_attacker",
7644 "auto_attack");
7645 if (reqs == NULL) {
7646 ok = FALSE;
7647 } else {
7649
7651 "auto_attack.attack_actions",
7652 filename)) {
7653 /* Failed to load auto attack actions */
7655 "\"%s\": %s: failed load %s.",
7656 filename, "auto_attack", "attack_actions");
7657 ok = FALSE;
7658 }
7659 }
7660
7661 /* Section: actions */
7662 if (ok) {
7663 action_iterate(act_id) {
7664 struct action *paction = action_by_number(act_id);
7665
7666 if (!load_action_blocked_by_list(file, filename, paction, compat)) {
7667 ok = FALSE;
7668 break;
7669 }
7671
7672 if (ok) {
7673 if (!lookup_bv_actions(file, filename,
7675 "actions.diplchance_initial_odds")) {
7676 ok = FALSE;
7677 }
7678 }
7679
7680 if (ok) {
7681 /* If the "Poison City" action or the "Poison City Escape" action
7682 * should empty the granary. */
7683 /* TODO: empty granary and reduce population should become separate
7684 * action effect flags when actions are generalized. */
7688 "actions.poison_empties_food_stock");
7689
7690 /* If the "Steal Maps" action or the "Steal Maps Escape" action always
7691 * will reveal all cities when successful. */
7695 "actions.steal_maps_reveals_all_cities");
7696
7697 /* Allow setting certain properties for some actions before
7698 * generalized actions. */
7699 action_iterate(act_id) {
7700 if (!load_action_range(file, act_id)) {
7701 ok = FALSE;
7702 } else if (!load_action_kind(file, act_id)) {
7703 ok = FALSE;
7704 } else if (!load_action_actor_consuming_always(file, act_id)) {
7705 ok = FALSE;
7706 } else {
7707 const char *entry_name = NULL;
7708
7709 if (!action_id_is_internal(act_id)) {
7711 }
7712
7713 if (compat->compat_mode && compat->version < RSFORMAT_3_3) {
7715 }
7716 }
7717
7718 if (!ok) {
7719 break;
7720 }
7722 }
7723
7724 if (ok) {
7725 /* The quiet (don't auto generate help for) property of all actions
7726 * live in a single enum vector. This avoids generic action
7727 * expectations. */
7728 if (secfile_entry_by_path(file, "actions.quiet_actions")) {
7730 size_t asize;
7731 int j;
7732
7735 "actions.quiet_actions");
7736
7737 if (!quiet_actions) {
7738 /* Entity exists but couldn't read it. */
7740 "\"%s\": actions.quiet_actions: bad action list",
7741 filename);
7742
7743 ok = FALSE;
7744 } else {
7745 for (j = 0; j < asize; j++) {
7746 /* Don't auto generate help text for this action. */
7748 }
7749
7751 }
7752 }
7753 }
7754
7755 if (ok) {
7756 /* Hard code action sub results for now. */
7757
7758 /* Unit Enter Hut */
7760 BV_SET(paction->sub_results, ACT_SUB_RES_HUT_ENTER);
7770
7771 /* Unit Frighten Hut */
7783
7784 /* Unit May Embark */
7785 action_iterate(act_id) {
7786 struct action *paction = action_by_number(act_id);
7787
7789 "civstyle.paradrop_to_transport")
7792 BV_SET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK);
7793 }
7794
7795 /* Embark actions will always embark, not maybe embark. */
7797
7798 /* Non Lethal bombard */
7805 }
7806 }
7807
7808 if (ok) {
7809 /* Forced actions after another action was successfully performed. */
7810
7811 if (!load_action_post_success_force(file, filename,
7815 ok = FALSE;
7816 } else if (!load_action_post_success_force(file, filename,
7820 ok = FALSE;
7821 } else if (!load_action_post_success_force(file, filename,
7824 ACTION_ATTACK))) {
7825 ok = FALSE;
7826 } else if (!load_action_post_success_force(file, filename,
7829 ACTION_ATTACK2))) {
7830 ok = FALSE;
7831 } else if (!load_action_post_success_force(file, filename,
7835 ok = FALSE;
7836 } else if (!load_action_post_success_force(file, filename,
7840 ok = FALSE;
7841 }
7842
7843 /* No "Suicide Attack". Can't act when dead. */
7844 }
7845
7846 if (ok) {
7847 /* The city that made the unit's current tile native is gone.
7848 * Evaluated against an adjacent tile. */
7850 auto_perf->cause = AAPC_CITY_GONE;
7851
7852 /* I have no objections to moving this out of game's actions to
7853 * cities.ruleset, units.ruleset or an other location in game.ruleset
7854 * you find more suitable. -- Sveinung */
7856 "actions.escape_city", filename)) {
7857 ok = FALSE;
7858 }
7859 }
7860
7861 if (ok) {
7862 /* The unit's stack has been defeated and is scheduled for execution
7863 * but the unit has the CanEscape unit type flag.
7864 * Evaluated against an adjacent tile. */
7867
7868 /* I have no objections to moving this out of game's actions to
7869 * cities.ruleset, units.ruleset or an other location in game.ruleset
7870 * you find more suitable. -- Sveinung */
7872 "actions.unit_stack_death", filename)) {
7873 ok = FALSE;
7874 }
7875 }
7876
7877 if (ok) {
7879 if (sec != nullptr) {
7880 section_list_iterate(sec, psection) {
7881 const char *sec_name = section_name(psection);
7882 const char *action_text;
7883 struct action *paction;
7884 const char *ui_name;
7885
7886 action_text = secfile_lookup_str(file, "%s.action", sec_name);
7887
7888 if (action_text == nullptr) {
7889 ruleset_error(nullptr, LOG_ERROR,
7890 "\"%s\" [%s] missing action to configure.",
7891 filename, sec_name);
7892 ok = FALSE;
7893 break;
7894 }
7895
7897 if (paction == nullptr) {
7898 ruleset_error(nullptr, LOG_ERROR,
7899 "\"%s\" [%s] lists unknown action type \"%s\".",
7900 filename, sec_name, action_text);
7901 ok = FALSE;
7902 break;
7903 }
7904
7905 if (paction->configured) {
7906 ruleset_error(nullptr, LOG_ERROR,
7907 "\"%s\" [%s] duplicate configuration for action \"%s\".",
7908 filename, sec_name, action_text);
7909 ok = FALSE;
7910 break;
7911 }
7912
7913 paction->configured = TRUE;
7914
7915 ui_name = secfile_lookup_str_default(file, nullptr,
7916 "%s.ui_name", sec_name);
7917 if (ui_name == nullptr) {
7919 }
7920 sz_strlcpy(paction->ui_name, ui_name);
7922 }
7923 }
7924
7925 if (ok) {
7926 action_iterate(act) {
7927 struct action *paction = action_by_number(act);
7928
7929 if (!paction->configured) {
7931 }
7933 }
7934
7935 if (ok) {
7937
7938 if (sec == nullptr && compat->compat_mode && compat->version < RSFORMAT_3_3) {
7941 }
7942
7943 if (sec != nullptr) {
7944 section_list_iterate(sec, psection) {
7945 struct action_enabler *enabler;
7946 const char *sec_name = section_name(psection);
7947 struct action *paction;
7948 struct requirement_vector *actor_reqs;
7949 struct requirement_vector *target_reqs;
7950 const char *action_text;
7951 const char *comment;
7952
7954
7955 action_text = secfile_lookup_str(file, "%s.action", sec_name);
7956
7957 if (action_text == nullptr) {
7958 ruleset_error(nullptr, LOG_ERROR,
7959 "\"%s\" [%s] missing action to enable.",
7960 filename, sec_name);
7961 ok = FALSE;
7962 break;
7963 }
7964
7966 if (paction == nullptr) {
7967 ruleset_error(nullptr, LOG_ERROR,
7968 "\"%s\" [%s] lists unknown action type \"%s\".",
7969 filename, sec_name, action_text);
7970 ok = FALSE;
7971 break;
7972 }
7973
7974 enabler->action = action_id(paction);
7975
7976 actor_reqs = lookup_req_list(file, compat, sec_name, "actor_reqs", action_text);
7977 if (actor_reqs == NULL) {
7978 ok = FALSE;
7979 break;
7980 }
7981
7982 requirement_vector_copy(&enabler->actor_reqs, actor_reqs);
7983
7984 target_reqs = lookup_req_list(file, compat, sec_name, "target_reqs", action_text);
7985 if (target_reqs == NULL) {
7986 ok = FALSE;
7987 break;
7988 }
7989
7990 requirement_vector_copy(&enabler->target_reqs, target_reqs);
7991
7992 comment = secfile_lookup_str(file, "%s.comment", sec_name);
7993 if (comment != nullptr) {
7994 enabler->rulesave.comment = fc_strdup(comment);
7995 }
7996
7999
8001 }
8002 }
8003
8004 return ok;
8005}
8006
8007/**********************************************************************/
8011static void send_ruleset_unit_classes(struct conn_list *dest)
8012{
8013 struct packet_ruleset_unit_class packet;
8015 int i;
8016
8017 for (i = 0; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
8018 const char *flagname;
8019 const char *helptxt;
8020
8022
8024 if (flagname == NULL) {
8025 fpacket.name[0] = '\0';
8026 } else {
8028 }
8029
8031 if (helptxt == NULL) {
8032 fpacket.helptxt[0] = '\0';
8033 } else {
8034 sz_strlcpy(fpacket.helptxt, helptxt);
8035 }
8036
8038 }
8039
8041 packet.id = uclass_number(c);
8042 sz_strlcpy(packet.name, untranslated_name(&c->name));
8043 sz_strlcpy(packet.rule_name, rule_name_get(&c->name));
8044 packet.min_speed = c->min_speed;
8045 packet.hp_loss_pct = c->hp_loss_pct;
8046 packet.non_native_def_pct = c->non_native_def_pct;
8047 packet.flags = c->flags;
8048
8049 PACKET_STRVEC_INSERT(packet.helptext, c->helptext);
8050
8051 lsend_packet_ruleset_unit_class(dest, &packet);
8053}
8054
8055/**********************************************************************/
8059static void send_ruleset_units(struct conn_list *dest)
8060{
8061 struct packet_ruleset_unit packet;
8062#ifdef FREECIV_WEB
8064#endif /* FREECIV_WEB */
8066 int i;
8067
8068 for (i = 0; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
8069 const char *flagname;
8070 const char *helptxt;
8071
8073
8075 if (flagname == NULL) {
8076 fpacket.name[0] = '\0';
8077 } else {
8079 }
8080
8082 if (helptxt == NULL) {
8083 fpacket.helptxt[0] = '\0';
8084 } else {
8085 sz_strlcpy(fpacket.helptxt, helptxt);
8086 }
8087
8089 }
8090
8092 packet.id = utype_number(u);
8093 sz_strlcpy(packet.name, untranslated_name(&u->name));
8094 sz_strlcpy(packet.rule_name, rule_name_get(&u->name));
8095 sz_strlcpy(packet.sound_move, u->sound_move);
8096 sz_strlcpy(packet.sound_move_alt, u->sound_move_alt);
8097 sz_strlcpy(packet.sound_fight, u->sound_fight);
8098 sz_strlcpy(packet.sound_fight_alt, u->sound_fight_alt);
8099 sz_strlcpy(packet.graphic_str, u->graphic_str);
8100 sz_strlcpy(packet.graphic_alt, u->graphic_alt);
8101 sz_strlcpy(packet.graphic_alt2, u->graphic_alt2);
8103 packet.build_cost = u->build_cost;
8104 packet.pop_cost = u->pop_cost;
8105 packet.attack_strength = u->attack_strength;
8106 packet.defense_strength = u->defense_strength;
8107 packet.move_rate = u->move_rate;
8108
8109 /* Shallow-copy (borrow) requirement vector */
8110 packet.build_reqs = u->build_reqs;
8111
8112 packet.vision_radius_sq = u->vision_radius_sq;
8113 packet.transport_capacity = u->transport_capacity;
8114 packet.hp = u->hp;
8115 packet.firepower = u->firepower;
8116 packet.obsoleted_by = u->obsoleted_by
8117 ? utype_number(u->obsoleted_by)
8118 : utype_count();
8119 packet.converted_to = u->converted_to
8120 ? utype_number(u->converted_to)
8121 : utype_count();
8122 packet.convert_time = u->convert_time;
8123 packet.fuel = u->fuel;
8124 packet.flags = u->flags;
8125 packet.roles = u->roles;
8126 packet.happy_cost = u->happy_cost;
8128 packet.upkeep[o] = u->upkeep[o];
8130 packet.paratroopers_range = u->paratroopers_range;
8131 packet.bombard_rate = u->bombard_rate;
8132 packet.city_size = u->city_size;
8133 packet.city_slots = u->city_slots;
8134 packet.tp_defense = u->tp_defense;
8135 packet.cargo = u->cargo;
8136 packet.targets = u->targets;
8137 packet.embarks = u->embarks;
8138 packet.disembarks = u->disembarks;
8139 packet.vlayer = u->vlayer;
8140
8141 if (u->veteran == NULL) {
8142 /* Use the default veteran system. */
8143 packet.veteran_levels = 0;
8144 } else {
8145 /* Per unit veteran system definition. */
8147
8148 for (i = 0; i < packet.veteran_levels; i++) {
8149 const struct veteran_level *vlevel = utype_veteran_level(u, i);
8150
8152 packet.power_fact[i] = vlevel->power_fact;
8153 packet.move_bonus[i] = vlevel->move_bonus;
8154 packet.base_raise_chance[i] = vlevel->base_raise_chance;
8155 packet.work_raise_chance[i] = vlevel->work_raise_chance;
8156 }
8157 }
8158 PACKET_STRVEC_INSERT(packet.helptext, u->helptext);
8159
8160 packet.worker = u->adv.worker;
8161
8162#ifdef FREECIV_WEB
8163 web_packet.id = utype_number(u);
8164
8165 BV_CLR_ALL(web_packet.utype_actions);
8166
8167 action_iterate(act) {
8168 if (utype_can_do_action(u, act)) {
8169 BV_SET(web_packet.utype_actions, act);
8170 }
8172#endif /* FREECIV_WEB */
8173
8174 lsend_packet_ruleset_unit(dest, &packet);
8176
8177 combat_bonus_list_iterate(u->bonuses, pbonus) {
8179
8180 bonuspacket.unit = packet.id;
8181 bonuspacket.flag = pbonus->flag;
8182 bonuspacket.type = pbonus->type;
8183 bonuspacket.value = pbonus->value;
8184 bonuspacket.quiet = pbonus->quiet;
8185
8189}
8190
8191/**********************************************************************/
8195static void send_ruleset_specialists(struct conn_list *dest)
8196{
8197 struct packet_ruleset_specialist packet;
8198
8201
8202 packet.id = spec_id;
8204 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
8208
8209 /* Shallow-copy (borrow) requirement vector */
8210 packet.reqs = s->reqs;
8211
8213
8214 lsend_packet_ruleset_specialist(dest, &packet);
8216}
8217/**********************************************************************/
8220static void send_ruleset_tech_classes(struct conn_list *dest)
8221{
8222 struct packet_ruleset_tech_class packet;
8223
8225 packet.id = ptclass->idx;
8226 sz_strlcpy(packet.name, untranslated_name(&ptclass->name));
8227 sz_strlcpy(packet.rule_name, rule_name_get(&ptclass->name));
8228 packet.cost_pct = ptclass->cost_pct;
8229
8230 lsend_packet_ruleset_tech_class(dest, &packet);
8232}
8233
8234/**********************************************************************/
8238static void send_ruleset_techs(struct conn_list *dest)
8239{
8240 struct packet_ruleset_tech packet;
8242 int i;
8243
8244 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
8245 const char *flagname;
8246 const char *helptxt;
8247
8248 fpacket.id = i + TECH_USER_1;
8249
8251 if (flagname == NULL) {
8252 fpacket.name[0] = '\0';
8253 } else {
8255 }
8256
8258 if (helptxt == NULL) {
8259 fpacket.helptxt[0] = '\0';
8260 } else {
8261 sz_strlcpy(fpacket.helptxt, helptxt);
8262 }
8263
8265 }
8266
8267 /* Since we have to prepend the tech requirements to the requirement
8268 * vector, we need to initialize a separate vector and deep-copy the
8269 * other requirements into it. */
8271
8272 advance_iterate(a) {
8273 packet.id = advance_number(a);
8274 packet.removed = !valid_advance(a);
8275 if (a->tclass == NULL) {
8276 packet.tclass = 0;
8277 } else {
8278 packet.tclass = a->tclass->idx;
8279 }
8280 sz_strlcpy(packet.name, untranslated_name(&a->name));
8281 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8282 sz_strlcpy(packet.graphic_str, a->graphic_str);
8283 sz_strlcpy(packet.graphic_alt, a->graphic_alt);
8284
8285 /* Reset requirement vector. */
8287
8288 /* The requirements req1 and req2 are needed to research a tech. Send
8289 * them in the research_reqs requirement vector. Range is set to player
8290 * since pooled research is configurable. */
8291
8292 if ((a->require[AR_ONE] != A_NEVER)
8293 && advance_number(a->require[AR_ONE]) > A_NONE) {
8294 struct requirement req
8296 FALSE, TRUE, FALSE,
8297 advance_number(a->require[AR_ONE]));
8299 }
8300
8301 if ((a->require[AR_TWO] != A_NEVER)
8302 && advance_number(a->require[AR_TWO]) > A_NONE) {
8303 struct requirement req
8305 FALSE, TRUE, FALSE,
8306 advance_number(a->require[AR_TWO]));
8308 }
8309
8310 /* The requirements of the tech's research_reqs also goes in the
8311 * packet's research_reqs requirement vector. */
8312 requirement_vector_iterate(&a->research_reqs, req) {
8315
8316 packet.root_req = a->require[AR_ROOT]
8317 ? advance_number(a->require[AR_ROOT])
8318 : advance_count();
8319
8320 packet.flags = a->flags;
8321 packet.cost = a->cost;
8322 packet.num_reqs = a->num_reqs;
8323 PACKET_STRVEC_INSERT(packet.helptext, a->helptext);
8324
8325 lsend_packet_ruleset_tech(dest, &packet);
8327
8329}
8330
8331/**********************************************************************/
8334static void send_ruleset_counters(struct conn_list *dest)
8335{
8337 struct packet_ruleset_counter packet;
8338
8339 sz_strlcpy(packet.name, untranslated_name(&pcount->name));
8340 sz_strlcpy(packet.rule_name, rule_name_get(&pcount->name));
8341 packet.checkpoint = pcount->checkpoint;
8342 packet.behavior = pcount->type;
8343 packet.type = pcount->target;
8344 packet.def = pcount->def;
8345
8346 PACKET_STRVEC_INSERT(packet.helptext, pcount->helptext);
8347 lsend_packet_ruleset_counter(dest, &packet);
8349}
8350
8351/**********************************************************************/
8355static void send_ruleset_buildings(struct conn_list *dest)
8356{
8357 int i;
8358
8359 for (i = 0; i < MAX_NUM_USER_BUILDING_FLAGS; i++) {
8361 const char *flagname;
8362 const char *helptxt;
8363
8365
8367 if (flagname == NULL) {
8368 fpacket.name[0] = '\0';
8369 } else {
8371 }
8372
8374 if (helptxt == NULL) {
8375 fpacket.helptxt[0] = '\0';
8376 } else {
8377 sz_strlcpy(fpacket.helptxt, helptxt);
8378 }
8379
8381 }
8382
8384 struct packet_ruleset_building packet;
8385
8386 packet.id = improvement_number(b);
8387 packet.genus = b->genus;
8388 sz_strlcpy(packet.name, untranslated_name(&b->name));
8389 sz_strlcpy(packet.rule_name, rule_name_get(&b->name));
8390 sz_strlcpy(packet.graphic_str, b->graphic_str);
8391 sz_strlcpy(packet.graphic_alt, b->graphic_alt);
8392 sz_strlcpy(packet.graphic_alt2, b->graphic_alt2);
8393
8394 /* Shallow-copy (borrow) requirement vectors */
8395 packet.reqs = b->reqs;
8396 packet.obs_reqs = b->obsolete_by;
8397
8398 packet.build_cost = b->build_cost;
8399 packet.upkeep = b->upkeep;
8400 packet.sabotage = b->sabotage;
8401 packet.flags = b->flags;
8402 sz_strlcpy(packet.soundtag, b->soundtag);
8403 sz_strlcpy(packet.soundtag_alt, b->soundtag_alt);
8404 sz_strlcpy(packet.soundtag_alt2, b->soundtag_alt2);
8405 PACKET_STRVEC_INSERT(packet.helptext, b->helptext);
8406
8407 lsend_packet_ruleset_building(dest, &packet);
8409}
8410
8411/**********************************************************************/
8415static void send_ruleset_terrain(struct conn_list *dest)
8416{
8417 struct packet_ruleset_terrain packet;
8419 int i;
8420
8422
8423 for (i = 0; i < MAX_NUM_USER_TER_FLAGS; i++) {
8424 const char *flagname;
8425 const char *helptxt;
8426
8427 fpacket.id = i + TER_USER_1;
8428
8430 if (flagname == NULL) {
8431 fpacket.name[0] = '\0';
8432 } else {
8434 }
8435
8437 if (helptxt == NULL) {
8438 fpacket.helptxt[0] = '\0';
8439 } else {
8440 sz_strlcpy(fpacket.helptxt, helptxt);
8441 }
8442
8444 }
8445
8446 terrain_type_iterate(pterrain) {
8447 packet.id = terrain_number(pterrain);
8448 packet.tclass = pterrain->tclass;
8449 packet.native_to = pterrain->native_to;
8450
8451 sz_strlcpy(packet.name, untranslated_name(&pterrain->name));
8452 sz_strlcpy(packet.rule_name, rule_name_get(&pterrain->name));
8453 sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
8454 sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
8455 sz_strlcpy(packet.graphic_alt2, pterrain->graphic_alt2);
8456
8457 packet.movement_cost = pterrain->movement_cost;
8458 packet.defense_bonus = pterrain->defense_bonus;
8459
8461 packet.output[o] = pterrain->output[o];
8463
8464 packet.num_resources = 0;
8465 terrain_resources_iterate(pterrain, res, freq) {
8466 packet.resources[packet.num_resources] = extra_number(res);
8467 packet.resource_freq[packet.num_resources] = freq;
8468 packet.num_resources++;
8470
8472 packet.road_output_incr_pct[o] = pterrain->road_output_incr_pct[o];
8474
8475 packet.base_time = pterrain->base_time;
8476 packet.road_time = pterrain->road_time;
8477
8478 packet.cultivate_result = (pterrain->cultivate_result
8479 ? terrain_number(pterrain->cultivate_result)
8480 : terrain_count());
8481 packet.cultivate_time = pterrain->cultivate_time;
8482
8483 packet.plant_result = (pterrain->plant_result
8484 ? terrain_number(pterrain->plant_result)
8485 : terrain_count());
8486 packet.plant_time = pterrain->plant_time;
8487
8488 packet.irrigation_food_incr = pterrain->irrigation_food_incr;
8489 packet.irrigation_time = pterrain->irrigation_time;
8490
8491 packet.mining_shield_incr = pterrain->mining_shield_incr;
8492 packet.mining_time = pterrain->mining_time;
8493
8494 packet.num_animals = 0;
8495 terrain_animals_iterate(pterrain, panimal) {
8496 packet.animals[packet.num_animals] = utype_number(panimal);
8497 packet.num_animals++;
8499
8500 packet.transform_result = (pterrain->transform_result
8501 ? terrain_number(pterrain->transform_result)
8502 : terrain_count());
8503 packet.placing_time = pterrain->placing_time;
8504 packet.pillage_time = pterrain->pillage_time;
8505 packet.transform_time = pterrain->transform_time;
8506
8508 for (i = 0; i < game.control.num_extra_types; i++) {
8509 packet.extra_removal_times[i] = pterrain->extra_removal_times[i];
8510 }
8511
8512 packet.flags = pterrain->flags;
8513
8514 packet.color_red = pterrain->rgb->r;
8515 packet.color_green = pterrain->rgb->g;
8516 packet.color_blue = pterrain->rgb->b;
8517
8518 PACKET_STRVEC_INSERT(packet.helptext, pterrain->helptext);
8519
8520 lsend_packet_ruleset_terrain(dest, &packet);
8522}
8523
8524/**********************************************************************/
8527static void send_ruleset_resources(struct conn_list *dest)
8528{
8529 struct packet_ruleset_resource packet;
8530
8532 packet.id = extra_index(presource);
8533
8535 packet.output[o] = presource->data.resource->output[o];
8537
8538 lsend_packet_ruleset_resource(dest, &packet);
8540}
8541
8542/**********************************************************************/
8546static void send_ruleset_extras(struct conn_list *dest)
8547{
8548 int i;
8549
8550 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
8552 const char *flagname;
8553 const char *helptxt;
8554
8556
8558 if (flagname == NULL) {
8559 fpacket.name[0] = '\0';
8560 } else {
8562 }
8563
8565 if (helptxt == NULL) {
8566 fpacket.helptxt[0] = '\0';
8567 } else {
8568 sz_strlcpy(fpacket.helptxt, helptxt);
8569 }
8570
8572 }
8573
8575 struct packet_ruleset_extra packet;
8576 int j;
8577
8578 packet.id = extra_number(e);
8579 sz_strlcpy(packet.name, untranslated_name(&e->name));
8580 sz_strlcpy(packet.rule_name, rule_name_get(&e->name));
8581
8582 packet.category = e->category;
8583
8584 BV_CLR_ALL(packet.causes);
8585 for (j = 0; j < EC_COUNT; j++) {
8586 if (is_extra_caused_by(e, j)) {
8587 BV_SET(packet.causes, j);
8588 }
8589 }
8590
8591 BV_CLR_ALL(packet.rmcauses);
8592 for (j = 0; j < ERM_COUNT; j++) {
8593 if (is_extra_removed_by(e, j)) {
8594 BV_SET(packet.rmcauses, j);
8595 }
8596 }
8597
8598 sz_strlcpy(packet.activity_gfx, e->activity_gfx);
8599 sz_strlcpy(packet.act_gfx_alt, e->act_gfx_alt);
8600 sz_strlcpy(packet.act_gfx_alt2, e->act_gfx_alt2);
8601 sz_strlcpy(packet.rmact_gfx, e->rmact_gfx);
8602 sz_strlcpy(packet.rmact_gfx_alt, e->rmact_gfx_alt);
8603 sz_strlcpy(packet.rmact_gfx_alt2, e->rmact_gfx_alt2);
8604 sz_strlcpy(packet.graphic_str, e->graphic_str);
8605 sz_strlcpy(packet.graphic_alt, e->graphic_alt);
8606
8607 /* Shallow-copy (borrow) requirement vectors */
8608 packet.reqs = e->reqs;
8609 packet.rmreqs = e->rmreqs;
8610
8611 packet.appearance_chance = e->appearance_chance;
8612 /* Shallow-copy (borrow) requirement vector */
8613 packet.appearance_reqs = e->appearance_reqs;
8614
8615 packet.disappearance_chance = e->disappearance_chance;
8616 /* Shallow-copy (borrow) requirement vector */
8617 packet.disappearance_reqs = e->disappearance_reqs;
8618
8619 packet.visibility_req = e->visibility_req;
8620 packet.buildable = e->buildable;
8621 packet.generated = e->generated;
8622 packet.build_time = e->build_time;
8623 packet.build_time_factor = e->build_time_factor;
8624 packet.removal_time = e->removal_time;
8625 packet.removal_time_factor = e->removal_time_factor;
8626 packet.infracost = e->infracost;
8627 packet.defense_bonus = e->defense_bonus;
8628 packet.eus = e->eus;
8629 packet.no_aggr_near_city = e->no_aggr_near_city;
8630
8631 packet.native_to = e->native_to;
8632
8633 packet.flags = e->flags;
8634 packet.hidden_by = e->hidden_by;
8635 packet.bridged_over = e->bridged_over;
8636 packet.conflicts = e->conflicts;
8637
8638 PACKET_STRVEC_INSERT(packet.helptext, e->helptext);
8639
8640 lsend_packet_ruleset_extra(dest, &packet);
8642}
8643
8644/**********************************************************************/
8648static void send_ruleset_bases(struct conn_list *dest)
8649{
8651 struct base_type *b = extra_base_get(pextra);
8652 struct packet_ruleset_base packet;
8653
8654 packet.id = base_number(b);
8655
8656 packet.gui_type = b->gui_type;
8657 packet.border_sq = b->border_sq;
8658 packet.vision_main_sq = b->vision_main_sq;
8659 packet.vision_invis_sq = b->vision_invis_sq;
8660 packet.vision_subs_sq = b->vision_subs_sq;
8661
8662 lsend_packet_ruleset_base(dest, &packet);
8664}
8665
8666/**********************************************************************/
8670static void send_ruleset_roads(struct conn_list *dest)
8671{
8672 struct packet_ruleset_road packet;
8673
8675 struct road_type *r = extra_road_get(pextra);
8676
8677 packet.id = road_number(r);
8678
8679 packet.gui_type = r->gui_type;
8680
8681 /* Shallow-copy (borrow) requirement vector */
8682 packet.first_reqs = r->first_reqs;
8683
8684 packet.move_cost = r->move_cost;
8685 packet.move_mode = r->move_mode;
8686
8688 packet.tile_incr_const[o] = r->tile_incr_const[o];
8689 packet.tile_incr[o] = r->tile_incr[o];
8690 packet.tile_bonus[o] = r->tile_bonus[o];
8692
8693 packet.compat = r->compat;
8694
8695 packet.integrates = r->integrates;
8696 packet.flags = r->flags;
8697
8698 lsend_packet_ruleset_road(dest, &packet);
8700}
8701
8702/**********************************************************************/
8706static void send_ruleset_goods(struct conn_list *dest)
8707{
8708 struct packet_ruleset_goods packet;
8709
8711 packet.id = goods_number(g);
8712 sz_strlcpy(packet.name, untranslated_name(&g->name));
8713 sz_strlcpy(packet.rule_name, rule_name_get(&g->name));
8714
8715 /* Shallow-copy (borrow) requirement vector */
8716 packet.reqs = g->reqs;
8717
8718 packet.from_pct = g->from_pct;
8719 packet.to_pct = g->to_pct;
8720 packet.onetime_pct = g->onetime_pct;
8721 packet.select_priority = g->select_priority;
8722 packet.replace_priority = g->replace_priority;
8723 packet.flags = g->flags;
8724
8725 PACKET_STRVEC_INSERT(packet.helptext, g->helptext);
8726
8727 lsend_packet_ruleset_goods(dest, &packet);
8729}
8730
8731/**********************************************************************/
8735static void send_ruleset_disasters(struct conn_list *dest)
8736{
8737 struct packet_ruleset_disaster packet;
8738
8740 packet.id = disaster_number(d);
8741
8742 sz_strlcpy(packet.name, untranslated_name(&d->name));
8743 sz_strlcpy(packet.rule_name, rule_name_get(&d->name));
8744
8745 /* Shallow-copy (borrow) requirement vector */
8746 packet.reqs = d->reqs;
8747
8748 packet.frequency = d->frequency;
8749
8750 packet.effects = d->effects;
8751
8752 lsend_packet_ruleset_disaster(dest, &packet);
8754}
8755
8756/**********************************************************************/
8760static void send_ruleset_achievements(struct conn_list *dest)
8761{
8762 struct packet_ruleset_achievement packet;
8763
8765 packet.id = achievement_number(a);
8766
8767 sz_strlcpy(packet.name, untranslated_name(&a->name));
8768 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8769
8770 packet.type = a->type;
8771 packet.unique = a->unique;
8772 packet.value = a->value;
8773
8774 lsend_packet_ruleset_achievement(dest, &packet);
8776}
8777
8778/**********************************************************************/
8781static void send_ruleset_actions(struct conn_list *dest)
8782{
8783 struct packet_ruleset_action packet;
8784
8785 action_iterate(act) {
8786 struct action *paction = action_by_number(act);
8787
8788 packet.id = act;
8790 packet.quiet = action_by_number(act)->quiet;
8791
8792 packet.result = paction->result;
8793 packet.sub_results = paction->sub_results;
8794 packet.actor_consuming_always = paction->actor_consuming_always;
8795
8796 packet.act_kind = action_by_number(act)->actor_kind;
8797 packet.tgt_kind = action_by_number(act)->target_kind;
8799
8802 packet.blocked_by = action_by_number(act)->blocked_by;
8803
8804 lsend_packet_ruleset_action(dest, &packet);
8806}
8807
8808/**********************************************************************/
8812{
8813 struct packet_ruleset_action_enabler packet;
8814
8817
8818 /* Shallow-copy (borrow) requirement vectors */
8819 packet.actor_reqs = enabler->actor_reqs;
8820 packet.target_reqs = enabler->target_reqs;
8821
8824}
8825
8826/**********************************************************************/
8831{
8832 int counter;
8833 int id;
8834 struct packet_ruleset_action_auto packet;
8835
8836 id = 0;
8838 packet.id = id++;
8839
8840 packet.cause = aperf->cause;
8841
8842 /* Shallow-copy (borrow) requirement vector */
8843 packet.reqs = aperf->reqs;
8844
8845 for (counter = 0;
8846 /* Can't list more actions than all actions. */
8848 /* ACTION_NONE terminates the list. */
8849 && aperf->alternatives[counter] != ACTION_NONE;
8850 counter++) {
8851 packet.alternatives[counter] = aperf->alternatives[counter];
8852 }
8853 packet.alternatives_count = counter;
8854
8855 lsend_packet_ruleset_action_auto(dest, &packet);
8857}
8858
8859/**********************************************************************/
8863static void send_ruleset_trade_routes(struct conn_list *dest)
8864{
8865 struct packet_ruleset_trade packet;
8867
8868 for (type = TRT_NATIONAL; type < TRT_LAST; type++) {
8870
8871 packet.id = type;
8872 packet.trade_pct = set->trade_pct;
8873 packet.cancelling = set->cancelling;
8874 packet.bonus_type = set->bonus_type;
8875
8876 lsend_packet_ruleset_trade(dest, &packet);
8877 }
8878}
8879
8880/**********************************************************************/
8884static void send_ruleset_governments(struct conn_list *dest)
8885{
8886 struct packet_ruleset_government gov;
8888
8890 /* Send one packet_government */
8891 gov.id = government_number(g);
8892
8893 /* Shallow-copy (borrow) requirement vector */
8894 gov.reqs = g->reqs;
8895
8896 sz_strlcpy(gov.name, untranslated_name(&g->name));
8897 sz_strlcpy(gov.rule_name, rule_name_get(&g->name));
8898 sz_strlcpy(gov.graphic_str, g->graphic_str);
8899 sz_strlcpy(gov.graphic_alt, g->graphic_alt);
8900 sz_strlcpy(gov.sound_str, g->sound_str);
8901 sz_strlcpy(gov.sound_alt, g->sound_alt);
8902 sz_strlcpy(gov.sound_alt2, g->sound_alt2);
8903 PACKET_STRVEC_INSERT(gov.helptext, g->helptext);
8904
8906
8907 /* Send one packet_government_ruler_title per ruler title. */
8909 const struct nation_type *pnation = ruler_title_nation(pruler_title);
8910
8911 title.gov = government_number(g);
8912 title.nation = pnation ? nation_number(pnation) : nation_count();
8913 sz_strlcpy(title.male_title,
8915 sz_strlcpy(title.female_title,
8920}
8921
8922/**********************************************************************/
8926static void send_ruleset_nations(struct conn_list *dest)
8927{
8930 struct packet_ruleset_nation packet;
8931 int i;
8932
8934 i = 0;
8939 i++;
8942
8944 i = 0;
8946 sz_strlcpy(groups_packet.groups[i],
8948 groups_packet.hidden[i] = pgroup->hidden;
8949 i++;
8952
8954 packet.id = nation_number(n);
8955 if (n->translation_domain == NULL) {
8956 packet.translation_domain[0] = '\0';
8957 } else {
8958 sz_strlcpy(packet.translation_domain, n->translation_domain);
8959 }
8960 sz_strlcpy(packet.adjective, untranslated_name(&n->adjective));
8961 sz_strlcpy(packet.rule_name, rule_name_get(&n->adjective));
8962 sz_strlcpy(packet.noun_plural, untranslated_name(&n->noun_plural));
8963 sz_strlcpy(packet.graphic_str, n->flag_graphic_str);
8964 sz_strlcpy(packet.graphic_alt, n->flag_graphic_alt);
8965
8966 i = 0;
8970 i++;
8972 packet.leader_count = i;
8973
8974 packet.style = style_number(n->style);
8975 packet.is_playable = n->is_playable;
8976 packet.barbarian_type = n->barb_type;
8977
8978 sz_strlcpy(packet.legend, n->legend);
8979
8980 i = 0;
8982 packet.sets[i++] = nation_set_number(pset);
8984 packet.nsets = i;
8985
8986 i = 0;
8988 packet.groups[i++] = nation_group_number(pgroup);
8990 packet.ngroups = i;
8991
8992 packet.init_government_id = n->init_government
8993 ? government_number(n->init_government) : government_count();
8994 fc_assert(ARRAY_SIZE(packet.init_techs) == ARRAY_SIZE(n->init_techs));
8995 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
8996 if (n->init_techs[i] != A_LAST) {
8997 packet.init_techs[i] = n->init_techs[i];
8998 } else {
8999 break;
9000 }
9001 }
9002 packet.init_techs_count = i;
9003 fc_assert(ARRAY_SIZE(packet.init_units) == ARRAY_SIZE(n->init_units));
9004 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
9005 const struct unit_type *t = n->init_units[i];
9006 if (t) {
9007 packet.init_units[i] = utype_number(t);
9008 } else {
9009 break;
9010 }
9011 }
9012 packet.init_units_count = i;
9014 == ARRAY_SIZE(n->init_buildings));
9015 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9016 if (n->init_buildings[i] != B_LAST) {
9017 /* Impr_type_id to int */
9018 packet.init_buildings[i] = n->init_buildings[i];
9019 } else {
9020 break;
9021 }
9022 }
9023 packet.init_buildings_count = i;
9024
9025 lsend_packet_ruleset_nation(dest, &packet);
9027
9028 /* Send initial values of is_pickable */
9030}
9031
9032/**********************************************************************/
9036static void send_ruleset_styles(struct conn_list *dest)
9037{
9038 struct packet_ruleset_style packet;
9039
9040 styles_iterate(s) {
9041 packet.id = style_index(s);
9042 sz_strlcpy(packet.name, untranslated_name(&s->name));
9043 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
9044
9045 lsend_packet_ruleset_style(dest, &packet);
9047}
9048
9049/**********************************************************************/
9052static void send_ruleset_clauses(struct conn_list *dest)
9053{
9054 struct packet_ruleset_clause packet;
9055 int i;
9056
9057 for (i = 0; i < CLAUSE_COUNT; i++) {
9058 struct clause_info *info = clause_info_get(i);
9059
9060 packet.type = i;
9061 packet.enabled = info->enabled;
9062
9063 /* Shallow-copy (borrow) requirement vectors */
9064 packet.giver_reqs = info->giver_reqs;
9065 packet.receiver_reqs = info->receiver_reqs;
9066 packet.either_reqs = info->either_reqs;
9067
9068 lsend_packet_ruleset_clause(dest, &packet);
9069 }
9070}
9071
9072/**********************************************************************/
9076static void send_ruleset_multipliers(struct conn_list *dest)
9077{
9078 multipliers_iterate(pmul) {
9079 struct packet_ruleset_multiplier packet;
9080
9081 packet.id = multiplier_number(pmul);
9082 packet.start = pmul->start;
9083 packet.stop = pmul->stop;
9084 packet.step = pmul->step;
9085 packet.def = pmul->def;
9086 packet.offset = pmul->offset;
9087 packet.factor = pmul->factor;
9088 packet.minimum_turns = pmul->minimum_turns;
9089
9090 sz_strlcpy(packet.name, untranslated_name(&pmul->name));
9091 sz_strlcpy(packet.rule_name, rule_name_get(&pmul->name));
9092
9093 /* Shallow-copy (borrow) requirement vector */
9094 packet.reqs = pmul->reqs;
9095
9096 PACKET_STRVEC_INSERT(packet.helptext, pmul->helptext);
9097
9098 lsend_packet_ruleset_multiplier(dest, &packet);
9100}
9101
9102/**********************************************************************/
9106static void send_ruleset_cities(struct conn_list *dest)
9107{
9109 int k;
9110
9111 for (k = 0; k < game.control.num_city_styles; k++) {
9112 city_p.style_id = k;
9113
9114 /* Shallow-copy (borrow) requirement vector */
9115 city_p.reqs = city_styles[k].reqs;
9116
9119 sz_strlcpy(city_p.graphic, city_styles[k].graphic);
9120 sz_strlcpy(city_p.graphic_alt, city_styles[k].graphic_alt);
9121 sz_strlcpy(city_p.citizens_graphic, city_styles[k].citizens_graphic);
9122
9124 }
9125}
9126
9127/**********************************************************************/
9131static void send_ruleset_musics(struct conn_list *dest)
9132{
9133 struct packet_ruleset_music packet;
9134
9136 packet.id = pmus->id;
9137
9138 sz_strlcpy(packet.music_peaceful, pmus->music_peaceful);
9139 sz_strlcpy(packet.music_combat, pmus->music_combat);
9140
9141 /* Shallow-copy (borrow) requirement vector */
9142 packet.reqs = pmus->reqs;
9143
9144 lsend_packet_ruleset_music(dest, &packet);
9146}
9147
9148/**********************************************************************/
9152static void send_ruleset_game(struct conn_list *dest)
9153{
9155 int i;
9156
9158
9159 /* Per unit veteran system definition. */
9160 misc_p.veteran_levels = game.veteran->levels;
9161
9162 for (i = 0; i < misc_p.veteran_levels; i++) {
9163 const struct veteran_level *vlevel = game.veteran->definitions + i;
9164
9165 sz_strlcpy(misc_p.veteran_name[i], untranslated_name(&vlevel->name));
9166 misc_p.power_fact[i] = vlevel->power_fact;
9167 misc_p.move_bonus[i] = vlevel->move_bonus;
9168 misc_p.base_raise_chance[i] = vlevel->base_raise_chance;
9169 misc_p.work_raise_chance[i] = vlevel->work_raise_chance;
9170 }
9171
9172 fc_assert(sizeof(misc_p.global_init_techs)
9173 == sizeof(game.rgame.global_init_techs));
9174 fc_assert(ARRAY_SIZE(misc_p.global_init_techs)
9176 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9178 misc_p.global_init_techs[i] = game.rgame.global_init_techs[i];
9179 } else {
9180 break;
9181 }
9182 }
9183 misc_p.global_init_techs_count = i;
9184
9185 fc_assert(ARRAY_SIZE(misc_p.global_init_buildings)
9187 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9189 /* Impr_type_id to int */
9190 misc_p.global_init_buildings[i] =
9192 } else {
9193 break;
9194 }
9195 }
9196 misc_p.global_init_buildings_count = i;
9197
9198 misc_p.default_specialist = DEFAULT_SPECIALIST;
9199
9201
9202 misc_p.background_red = game.plr_bg_color->r;
9203 misc_p.background_green = game.plr_bg_color->g;
9204 misc_p.background_blue = game.plr_bg_color->b;
9205
9207}
9208
9209/**********************************************************************/
9213static void send_ruleset_team_names(struct conn_list *dest)
9214{
9216
9218 const char *name = team_slot_defined_name(tslot);
9219
9220 if (NULL == name) {
9221 /* End of defined names. */
9222 break;
9223 }
9224
9226 sz_strlcpy(team_name_info_p.team_name, name);
9227
9230}
9231
9232/**********************************************************************/
9235static void notify_ruleset_fallback(const char *msg)
9236{
9238}
9239
9240/**********************************************************************/
9243bool load_rulesets(const char *restore, const char *alt, bool compat_mode,
9244 rs_conversion_logger logger,
9245 bool act, bool buffer_script, bool load_luadata)
9246{
9247 set_ruleset_compat_mode(compat_mode);
9248
9249 if (load_rulesetdir(game.server.rulesetdir, compat_mode, logger,
9250 act, buffer_script, load_luadata)) {
9252 return TRUE;
9253 }
9254
9255 if (alt != NULL) {
9256 if (load_rulesetdir(alt, compat_mode, logger, act, buffer_script,
9257 load_luadata)) {
9259
9261 return TRUE;
9262 }
9263 }
9264
9265 /* Fallback to previous one. */
9266 if (restore != NULL) {
9267 if (load_rulesetdir(restore, compat_mode, logger, act, buffer_script, TRUE)) {
9269
9270 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Keeping previous one."));
9271
9273
9274 /* We're in sane state as restoring previous ruleset succeeded,
9275 * but return failure to indicate that this is not what caller
9276 * wanted. */
9277 return FALSE;
9278 }
9279 }
9280
9282
9283 /* Fallback to default one, but not if that's what we tried already */
9287 /* We're in sane state as fallback ruleset loading succeeded,
9288 * but return failure to indicate that this is not what caller
9289 * wanted. */
9291
9292 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Switching to default one."));
9293
9294 return FALSE;
9295 }
9296 }
9297
9298#ifdef FREECIV_WEB
9299 log_normal(_("Cannot load any ruleset. Freeciv-web ruleset is available from "
9300 "https://github.com/freeciv/freeciv-web"));
9301#endif /* FREECIV_WEB */
9302
9303 /* Cannot load even default ruleset, we're in completely unusable state */
9305
9307}
9308
9309/**********************************************************************/
9313{
9314 if (file != NULL) {
9315 secfile_destroy(file);
9316 }
9317}
9318
9319/**********************************************************************/
9328
9329/**********************************************************************/
9333static bool load_rulesetdir(const char *rsdir, bool compat_mode,
9334 rs_conversion_logger logger,
9335 bool act, bool buffer_script, bool load_luadata)
9336{
9339 struct section_file *actionfile;
9340 bool ok = TRUE;
9342
9343 log_normal(_("Loading rulesets."));
9344
9346 compat_info.compat_mode = compat_mode;
9347 compat_info.log_cb = logger;
9348
9350 /* Reset the list of available player colors. */
9354
9355 if (script_buffer != NULL) {
9358 }
9359 if (parser_buffer != NULL) {
9362 }
9363
9364 server.playable_nations = 0;
9365
9369 buildfile = openload_ruleset_file("buildings", rsdir);
9370 govfile = openload_ruleset_file("governments", rsdir);
9372 terrfile = openload_ruleset_file("terrain", rsdir);
9377
9378 if (load_luadata) {
9380 } else {
9382 }
9383
9384 if (techfile == NULL
9385 || buildfile == NULL
9386 || govfile == NULL
9387 || unitfile == NULL
9388 || terrfile == NULL
9389 || stylefile == NULL
9390 || cityfile == NULL
9391 || nationfile == NULL
9392 || effectfile == NULL
9393 || actionfile == NULL
9394 || gamefile == NULL) {
9395 ok = FALSE;
9396 }
9397
9398 if (ok) {
9399 /* Note: Keep load_game_names() first so that compat_info.version is
9400 * correctly initialized. */
9410 }
9411
9412 if (ok) {
9414 }
9415
9416 if (ok) {
9418 }
9419 if (ok) {
9421 }
9422 if (ok) {
9424 }
9425 if (ok) {
9427 }
9428 if (ok) {
9429 /* Terrain must precede nations and units */
9431 }
9432 if (ok) {
9434 }
9435 if (ok) {
9437 }
9438 if (ok) {
9440 }
9441 if (ok) {
9443 }
9444 if (ok) {
9446 }
9447 if (ok) {
9449 }
9450
9451 if (ok) {
9452 /* Init nations we just loaded. */
9454
9455 /* Needed by role_unit_precalcs(). */
9457
9458 /* Prepare caches we want to sanity check. */
9462
9465 }
9466
9467 if (ok) {
9468 /* Only load settings for a sane ruleset */
9469 ok = settings_ruleset(gamefile, "settings", act,
9470 compat_info.compat_mode
9471 && compat_info.version < RSFORMAT_CURRENT);
9472
9473 if (ok) {
9475 }
9476 }
9477
9489
9490 if (extra_sections) {
9493 }
9494 if (base_sections) {
9497 }
9498 if (road_sections) {
9501 }
9502 if (resource_sections) {
9505 }
9506 if (terrain_sections) {
9509 }
9510
9511 if (ok) {
9513 }
9514
9515 if (ok) {
9516 char **buffer = buffer_script ? &script_buffer : NULL;
9517
9519
9521
9522 ok = (openload_script_file("script", rsdir, buffer, FALSE) == TRI_YES);
9523 }
9524
9525 if (ok) {
9526 enum fc_tristate pret;
9527 char **buffer = buffer_script ? &parser_buffer : NULL;
9528
9529 pret = openload_script_file("parser", rsdir, buffer, compat_info.compat_mode);
9530
9531 if (pret == TRI_MAYBE && buffer_script) {
9533 "-- This file is for lua-functionality for parsing luadata.txt\n-- of this ruleset.");
9534 }
9535
9536 ok = (pret != TRI_NO);
9537 }
9538
9539 if (ok && !buffer_script) {
9540 ok = (openload_script_file("default", rsdir, NULL, FALSE) == TRI_YES);
9541 }
9542
9543 if (ok && act) {
9544 /* Populate remaining caches. */
9551 ptype->unknown_move_cost = utype_unknown_move_cost(ptype);
9555
9556 /* Build advisors unit class cache corresponding to loaded rulesets */
9558 CALL_FUNC_EACH_AI(units_ruleset_init);
9559
9560 /* We may need to adjust the number of AI players
9561 * if the number of available nations changed. */
9563 }
9564
9565 return ok;
9566}
9567
9568/**********************************************************************/
9572{
9573 struct section_file *file;
9574 bool ok = TRUE;
9575
9577 if (file == NULL) {
9579 "Could not load game.ruleset:\n%s",
9580 secfile_error());
9581 ok = FALSE;
9582 }
9583 if (ok) {
9584 settings_ruleset(file, "settings", TRUE, FALSE);
9585 secfile_destroy(file);
9586 }
9587
9588 return ok;
9589}
9590
9591/**********************************************************************/
9594void send_rulesets(struct conn_list *dest)
9595{
9597
9598 /* ruleset_control also indicates to client that ruleset sending starts. */
9600
9601 /* Currently containing control-kind of data of nation sets and groups,
9602 * this too must be sent before any requirement vector may depend on
9603 * that data. */
9605
9606 send_ruleset_game(dest);
9616 send_ruleset_techs(dest);
9619 send_ruleset_units(dest);
9621 send_ruleset_extras(dest);
9622 send_ruleset_bases(dest);
9623 send_ruleset_roads(dest);
9626 send_ruleset_goods(dest);
9628 send_ruleset_styles(dest);
9630 send_ruleset_cities(dest);
9632 send_ruleset_musics(dest);
9633 send_ruleset_cache(dest);
9634
9635 /* Indicate client that all rulesets have now been sent. */
9637
9638 /* changed game settings will be send in
9639 * connecthand.c:establish_new_connection() */
9640
9642}
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:5718
void actions_rs_pre_san_gen(void)
Definition actions.c:889
const char * action_min_range_ruleset_var_name(int act)
Definition actions.c:6465
const char * action_blocked_by_ruleset_var_name(const struct action *act)
Definition actions.c:7175
bool action_is_in_use(struct action *paction)
Definition actions.c:5672
const char * action_post_success_forced_ruleset_var_name(const struct action *act)
Definition actions.c:7369
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:7002
const char * action_max_range_ruleset_var_name(int act)
Definition actions.c:6643
const char * action_target_kind_ruleset_var_name(int act)
Definition actions.c:6830
void action_enabler_add(struct action_enabler *enabler)
Definition actions.c:1526
const char * action_ui_name_default(int act)
Definition actions.c:6101
struct action_enabler * action_enabler_new(void)
Definition actions.c:1475
bool action_enabler_possible_actor(const struct action_enabler *ae)
Definition actions.c:5607
bool action_id_is_internal(action_id act)
Definition actions.c:5710
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:5803
#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:511
#define MAX_DISASTER_TYPES
Definition fc_types.h:52
#define MAX_VET_LEVELS
Definition fc_types.h:49
@ ROCO_RAILROAD
Definition fc_types.h:960
@ ROCO_NONE
Definition fc_types.h:960
@ ROCO_RIVER
Definition fc_types.h:960
@ ROCO_ROAD
Definition fc_types.h:960
#define MAX_GRANARY_INIS
Definition fc_types.h:73
#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:823
#define EC_SPECIAL
Definition fc_types.h:821
int action_id
Definition fc_types.h:249
#define SP_MAX
Definition fc_types.h:268
#define EC_NONE
Definition fc_types.h:820
#define EC_NOT_AGGRESSIVE
Definition fc_types.h:824
#define EC_DEFENSIVE
Definition fc_types.h:822
#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:127
#define MAX_ACHIEVEMENT_TYPES
Definition fc_types.h:53
#define MAX_LEN_NAME
Definition fc_types.h:67
#define MAX_NUM_TECH_LIST
Definition fc_types.h:44
#define MAX_LEN_CITYNAME
Definition fc_types.h:68
#define MAX_COUNTERS
Definition fc_types.h:107
#define UCL_LAST
Definition fc_types.h:275
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
#define Qn_(String)
Definition fcintl.h:89
#define N_(String)
Definition fcintl.h:69
const struct ft_color ftc_warning
struct civ_game game
Definition game.c: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:902
#define RS_DEFAULT_BASE_BRIBE_COST
Definition game.h:870
#define RS_MAX_INCITE_BASE_COST
Definition game.h:812
#define RS_DEFAULT_TECH_UPKEEP_DIVIDER
Definition game.h:884
#define RS_DEFAULT_HAPPY_COST
Definition game.h:854
#define RS_MIN_UPGRADE_VETERAN_LOSS
Definition game.h:881
#define RS_MIN_ILLNESS_MIN_SIZE
Definition game.h:785
#define RS_DEFAULT_POISON_EMPTIES_FOOD_STOCK
Definition game.h:892
#define RS_DEFAULT_GRANARY_FOOD_INC
Definition game.h:828
#define RS_DEFAULT_ILLNESS_ON
Definition game.h:778
#define RS_MAX_FOOD_COST
Definition game.h:860
#define RS_MAX_HAPPY_COST
Definition game.h:856
#define GAME_DEFAULT_CELEBRATESIZE
Definition game.h:507
#define RS_MIN_ILLNESS_BASE_FACTOR
Definition game.h:781
#define RS_DEFAULT_STEAL_MAP_REVEALS_CITIES
Definition game.h:893
#define RS_MIN_TECH_UPKEEP_DIVIDER
Definition game.h:885
#define RS_MAX_RANSOM_GOLD
Definition game.h:876
#define RS_MIN_HAPPY_COST
Definition game.h:855
#define RS_MIN_BORDER_RADIUS_SQ_CITY
Definition game.h:799
#define GAME_DEFAULT_RULESETDIR
Definition game.h:681
#define RS_MIN_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:867
#define RS_MAX_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:808
#define RS_DEFAULT_UPGRADE_VETERAN_LOSS
Definition game.h:880
#define RS_MAX_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:868
#define RS_MAX_INCITE_UNIT_FCT
Definition game.h:820
#define RS_MIN_VIS_RADIUS_SQ
Definition game.h:846
#define RS_DEFAULT_CALENDAR_SKIP_0
Definition game.h:796
#define RS_MAX_ILLNESS_MIN_SIZE
Definition game.h:786
#define RS_DEFAULT_CITY_RADIUS_SQ
Definition game.h:841
#define RS_DEFAULT_HP
Definition game.h:888
#define GAME_DEFAULT_START_YEAR
Definition game.h:748
#define RS_MAX_BORDER_SIZE_EFFECT
Definition game.h:804
#define RS_DEFAULT_BORDER_SIZE_EFFECT
Definition game.h:802
#define RS_MAX_BASE_BRIBE_COST
Definition game.h:872
#define RS_MIN_INCITE_BASE_COST
Definition game.h:811
#define RS_DEFAULT_PILLAGE_SELECT
Definition game.h:878
#define RS_MIN_CITY_RADIUS_SQ
Definition game.h:842
#define RS_MIN_CITY_CENTER_OUTPUT
Definition game.h:833
#define RS_MAX_GRANARY_FOOD_INC
Definition game.h:830
#define RS_MAX_CITY_CENTER_OUTPUT
Definition game.h:834
#define RS_MAX_CITY_RADIUS_SQ
Definition game.h:843
#define RS_DEFAULT_POS_YEAR_LABEL
Definition game.h:774
#define RS_MIN_INCITE_UNIT_FCT
Definition game.h:819
#define RS_MIN_BORDER_SIZE_EFFECT
Definition game.h:803
#define RS_DEFAULT_VIS_RADIUS_SQ
Definition game.h:845
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:806
#define RS_DEFAULT_TIRED_ATTACK
Definition game.h:862
#define RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS
Definition game.h:894
#define RS_MAX_ILLNESS_POLLUTION_PCT
Definition game.h:794
#define RS_DEFAULT_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:788
#define RS_DEFAULT_FOOD_COST
Definition game.h:858
#define RS_DEFAULT_INCITE_UNIT_FCT
Definition game.h:818
#define RS_MAX_INCITE_TOTAL_FCT
Definition game.h:824
#define RS_DEFAULT_INCITE_BASE_COST
Definition game.h:810
#define GAME_DEFAULT_ANGRYCITIZEN
Definition game.h:398
#define RS_DEFAULT_CITY_CENTER_OUTPUT
Definition game.h:832
#define RS_MIN_HP
Definition game.h:889
#define RS_MIN_INCITE_TOTAL_FCT
Definition game.h:823
#define RS_DEFAULT_ILLNESS_POLLUTION_PCT
Definition game.h:792
#define RS_MAX_UPGRADE_VETERAN_LOSS
Definition game.h:882
static void set_ruleset_compat_mode(bool active)
Definition game.h:362
#define RS_MAX_VIS_RADIUS_SQ
Definition game.h:847
#define RS_MIN_GRANARY_FOOD_INC
Definition game.h:829
#define RS_MAX_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:790
#define RS_MAX_HP
Definition game.h:890
#define RS_DEFAULT_ILLNESS_MIN_SIZE
Definition game.h:784
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY
Definition game.h:798
const struct nation_type * ruler_title_nation(const struct ruler_title *pruler_title)
Definition government.c:369
struct ruler_title * government_ruler_title_new(struct government *pgovern, const struct nation_type *pnation, const char *ruler_male_title, const char *ruler_female_title)
Definition government.c:329
const char * ruler_title_female_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:387
Government_type_id government_count(void)
Definition government.c:71
const char * ruler_title_male_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:378
void governments_alloc(int num)
Definition government.c:533
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
const struct ruler_title_hash * government_ruler_titles(const struct government *pgovern)
Definition government.c:318
Government_type_id government_index(const struct government *pgovern)
Definition government.c:82
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
#define governments_iterate(NAME_pgov)
Definition government.h:124
#define G_LAST
Definition government.h:48
#define ruler_titles_iterate(ARG_hash, NAME_rule_title)
Definition government.h:38
#define ruler_titles_iterate_end
Definition government.h:41
#define governments_iterate_end
Definition government.h:127
const char * title
Definition repodlgs.c:1314
GType type
Definition repodlgs.c:1313
struct impr_type * improvement_by_number(const Impr_type_id id)
Impr_type_id improvement_number(const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
void improvement_feature_cache_init(void)
Definition improvement.c:92
struct impr_type * improvement_by_rule_name(const char *name)
void set_user_impr_flag_name(enum impr_flag_id id, const char *name, const char *helptxt)
const char * impr_flag_helptxt(enum impr_flag_id id)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define B_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:978
#define SINGLE_MOVE
Definition movement.h:26
const char * multiplier_rule_name(const struct multiplier *pmul)
Multiplier_type_id multiplier_number(const struct multiplier *pmul)
Definition multipliers.c:67
struct multiplier * multiplier_by_rule_name(const char *name)
Multiplier_type_id multiplier_index(const struct multiplier *pmul)
Definition multipliers.c:80
#define multipliers_iterate(_mul_)
Definition multipliers.h:61
#define multipliers_iterate_end
Definition multipliers.h:67
static void name_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name)
static const char * rule_name_get(const struct name_translation *ptrans)
static const char * untranslated_name(const struct name_translation *ptrans)
static void names_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name, const char *rule_name)
void nation_group_set_match(struct nation_group *pgroup, int match)
Definition nation.c: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:1617
#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:429
static void ruleset_load_traits(struct trait_limits *out, struct section_file *file, const char *secname, const char *field_prefix)
Definition ruleload.c:1274
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:9333
#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:1175
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:1950
static bool load_terrain_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2748
static bool load_style_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5636
int ruleset_purge_unused_entities(void)
Definition ruleload.c:319
#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:4341
#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:8238
#define section_strlcpy(dst, src)
Definition ruleload.c:123
static bool load_action_range(struct section_file *file, action_id act)
Definition ruleload.c:6340
#define check_name(name)
Definition ruleload.c:117
static void send_ruleset_units(struct conn_list *dest)
Definition ruleload.c:8059
static void send_ruleset_governments(struct conn_list *dest)
Definition ruleload.c:8884
static bool load_action_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1443
static struct extra_type * lookup_resource(const char *filename, const char *name, const char *jsection)
Definition ruleload.c:1154
static struct section_file * openload_luadata_file(const char *rsdir)
Definition ruleload.c:632
static bool load_ruleset_techs(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1581
static bool purge_unused_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:333
void rulesets_deinit(void)
Definition ruleload.c:9323
static void send_ruleset_resources(struct conn_list *dest)
Definition ruleload.c:8527
static bool load_ruleset_buildings(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2624
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:1006
static void nullcheck_secfile_destroy(struct section_file *file)
Definition ruleload.c:9312
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:6261
static void send_ruleset_clauses(struct conn_list *dest)
Definition ruleload.c:9052
static void send_ruleset_game(struct conn_list *dest)
Definition ruleload.c:9152
char * parser_buffer
Definition ruleload.c:215
#define NATION_SECTION_PREFIX
Definition ruleload.c:97
static bool load_ruleset_effects(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:6087
static bool lookup_cbonus_list(struct combat_bonus_list *list, struct section_file *file, const char *sec, const char *sub)
Definition ruleload.c:791
static void send_ruleset_nations(struct conn_list *dest)
Definition ruleload.c:8926
static void send_ruleset_roads(struct conn_list *dest)
Definition ruleload.c:8670
static int ruleset_purge_unused_enablers(void)
Definition ruleload.c:250
#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:4733
static void send_ruleset_tech_classes(struct conn_list *dest)
Definition ruleload.c:8220
static void send_ruleset_action_enablers(struct conn_list *dest)
Definition ruleload.c:8811
static void send_ruleset_control(struct conn_list *dest)
Definition ruleload.c:4539
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:9243
#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:221
#define TERRAIN_SECTION_PREFIX
Definition ruleload.c:106
static struct section_file * openload_ruleset_file(const char *whichset, const char *rsdir)
Definition ruleload.c:577
static void send_ruleset_musics(struct conn_list *dest)
Definition ruleload.c:9131
int ruleset_purge_redundant_reqs(void)
Definition ruleload.c:496
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:8706
static const char name_too_long[]
Definition ruleload.c:121
bool reload_rulesets_settings(void)
Definition ruleload.c:9571
static struct strvec * lookup_strvec(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleload.c:1134
#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:850
static bool load_game_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1313
static void send_ruleset_counters(struct conn_list *dest)
Definition ruleload.c:8334
static void send_ruleset_specialists(struct conn_list *dest)
Definition ruleload.c:8195
#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:8830
static bool load_government_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4259
static int char * script_buffer
Definition ruleload.c:214
static bool load_action_blocked_by_list(struct section_file *file, const char *filename, struct action *paction, struct rscompat_info *compat)
Definition ruleload.c:6405
static void send_ruleset_team_names(struct conn_list *dest)
Definition ruleload.c:9213
static void send_ruleset_cities(struct conn_list *dest)
Definition ruleload.c:9106
static bool purge_redundant_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:418
static char * lookup_string(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleload.c:1114
static const char * check_leader_names(struct nation_type *pnation)
Definition ruleload.c:4577
#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:467
static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir, char **buffer, bool optional)
Definition ruleload.c:605
char * get_parser_buffer(void)
Definition ruleload.c:568
#define ACTION_SECTION_PREFIX
Definition ruleload.c:113
static bool load_building_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2543
#define EXTRA_SECTION_PREFIX
Definition ruleload.c:100
void send_rulesets(struct conn_list *dest)
Definition ruleload.c:9594
#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:882
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:5876
static bool load_ruleset_styles(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5697
static struct government * lookup_government(struct section_file *file, const char *entry, const char *filename, struct government *fallback)
Definition ruleload.c:1089
static bool load_ruleset_units(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2071
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:1225
static void send_ruleset_styles(struct conn_list *dest)
Definition ruleload.c:9036
#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:660
static void send_ruleset_disasters(struct conn_list *dest)
Definition ruleload.c:8735
static bool purge_duplicate_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:373
static bool lookup_tech_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleload.c:942
#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:6547
static bool load_nation_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4597
static void send_ruleset_achievements(struct conn_list *dest)
Definition ruleload.c:8760
#define SCRIPT_SUFFIX
Definition ruleload.c:85
static void send_ruleset_bases(struct conn_list *dest)
Definition ruleload.c:8648
static bool load_ruleset_terrain(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:3080
static int ruleset_purge_unused_effects(void)
Definition ruleload.c:296
static bool load_action_actor_consuming_always(struct section_file *file, action_id act)
Definition ruleload.c:6388
static bool load_action_post_success_force(struct section_file *file, const char *filename, int performer_slot, struct action *paction)
Definition ruleload.c:6476
static bool load_tech_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1463
#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:6365
static void send_ruleset_multipliers(struct conn_list *dest)
Definition ruleload.c:9076
char * get_script_buffer(void)
Definition ruleload.c:560
static void send_ruleset_actions(struct conn_list *dest)
Definition ruleload.c:8781
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:4749
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:5775
static bool load_ruleset_nations(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4919
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:5818
static void send_ruleset_unit_classes(struct conn_list *dest)
Definition ruleload.c:8011
#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:1058
static void send_ruleset_extras(struct conn_list *dest)
Definition ruleload.c:8546
#define rs_sanity_veteran(_path, _entry, _i, _condition, _action)
static void send_ruleset_terrain(struct conn_list *dest)
Definition ruleload.c:8415
#define GOVERNMENT_SECTION_PREFIX
Definition ruleload.c:94
static bool load_unit_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1792
static void send_ruleset_trade_routes(struct conn_list *dest)
Definition ruleload.c:8863
static bool load_ruleset_actions(struct section_file *file, struct section_file *gamefile, struct rscompat_info *compat)
Definition ruleload.c:7612
static void notify_ruleset_fallback(const char *msg)
Definition ruleload.c:9235
static bool lookup_bv_actions(struct section_file *file, const char *filename, bv_actions *target, const char *path)
Definition ruleload.c:6513
static void send_ruleset_buildings(struct conn_list *dest)
Definition ruleload.c:8355
#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:1251
#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:515
static bool load_action_range_max(struct section_file *file, action_id act)
Definition ruleload.c:6299
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:5854
#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:2505
void update_nations_with_startpos(void)
Definition srv_main.c:2310
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
int animals[MAX_NUM_ANIMALS]
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:609
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:185
Terrain_type_id terrain_count(void)
Definition terrain.c:117
const char * terrain_flag_id_name_cb(enum terrain_flag_id flag)
Definition terrain.c:816
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:137
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:155
const char * terrain_flag_helptxt(enum terrain_flag_id id)
Definition terrain.c:828
struct resource_type * resource_type_init(struct extra_type *pextra)
Definition terrain.c:271
void set_user_terrain_flag_name(enum terrain_flag_id id, const char *name, const char *helptxt)
Definition terrain.c:787
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:146
#define RESOURCE_FREQUENCY_MAXIMUM
Definition terrain.h:102
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define terrain_animals_iterate(pterrain, _animal)
Definition terrain.h:299
#define T_NONE
Definition terrain.h:61
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:273
#define RESOURCE_NONE_IDENTIFIER
Definition terrain.h:52
#define RESOURCE_NULL_IDENTIFIER
Definition terrain.h:51
#define RESOURCE_FREQUENCY_MINIMUM
Definition terrain.h:100
#define MAX_NUM_TERRAINS
Definition terrain.h:69
#define T_FIRST
Definition terrain.h:65
#define MAX_NUM_USER_TER_FLAGS
Definition terrain.h:32
#define terrain_resources_iterate_end
Definition terrain.h:295
#define terrain_resources_iterate(pterrain, _res, _freq)
Definition terrain.h:286
#define terrain_animals_iterate_end
Definition terrain.h:307
#define RESOURCE_FREQUENCY_DEFAULT
Definition terrain.h:101
#define ACTIVITY_FACTOR
Definition tile.h:170
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