Freeciv-3.1
Loading...
Searching...
No Matches
ruleset.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdarg.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23/* utility */
24#include "bitvector.h"
25#include "deprecations.h"
26#include "fcintl.h"
27#include "log.h"
28#include "mem.h"
29#include "registry.h"
30#include "shared.h"
31#include "string_vector.h"
32#include "support.h"
33
34/* common */
35#include "achievements.h"
36#include "actions.h"
37#include "ai.h"
38#include "base.h"
39#include "capability.h"
40#include "city.h"
41#include "effects.h"
42#include "extras.h"
43#include "fc_types.h"
44#include "featured_text.h"
45#include "game.h"
46#include "government.h"
47#include "map.h"
48#include "movement.h"
49#include "multipliers.h"
50#include "name_translation.h"
51#include "nation.h"
52#include "packets.h"
53#include "player.h"
54#include "requirements.h"
55#include "rgbcolor.h"
56#include "road.h"
57#include "specialist.h"
58#include "style.h"
59#include "tech.h"
60#include "traderoutes.h"
61#include "unit.h"
62#include "unittype.h"
63
64/* server */
65#include "citytools.h"
66#include "notify.h"
67#include "plrhand.h"
68#include "rscompat.h"
69#include "rssanity.h"
70#include "settings.h"
71#include "srv_main.h"
72
73/* server/advisors */
74#include "advruleset.h"
75
76/* server/scripting */
77#include "script_server.h"
78
79#include "ruleset.h"
80
81/* RULESET_SUFFIX already used, no leading dot here */
82#define RULES_SUFFIX "ruleset"
83#define SCRIPT_SUFFIX "lua"
84
85#define ADVANCE_SECTION_PREFIX "advance_"
86#define TECH_CLASS_SECTION_PREFIX "techclass_"
87#define BUILDING_SECTION_PREFIX "building_"
88#define CITYSTYLE_SECTION_PREFIX "citystyle_"
89#define MUSICSTYLE_SECTION_PREFIX "musicstyle_"
90#define EFFECT_SECTION_PREFIX "effect_"
91#define GOVERNMENT_SECTION_PREFIX "government_"
92#define NATION_SET_SECTION_PREFIX "nset" /* without underscore? */
93#define NATION_GROUP_SECTION_PREFIX "ngroup" /* without underscore? */
94#define NATION_SECTION_PREFIX "nation" /* without underscore? */
95#define STYLE_SECTION_PREFIX "style_"
96#define CLAUSE_SECTION_PREFIX "clause_"
97#define EXTRA_SECTION_PREFIX "extra_"
98#define BASE_SECTION_PREFIX "base_"
99#define ROAD_SECTION_PREFIX "road_"
100#define RESOURCE_SECTION_PREFIX "resource_"
101#define GOODS_SECTION_PREFIX "goods_"
102#define SPECIALIST_SECTION_PREFIX "specialist_"
103#define TERRAIN_SECTION_PREFIX "terrain_"
104#define UNIT_CLASS_SECTION_PREFIX "unitclass_"
105#define UNIT_SECTION_PREFIX "unit_"
106#define DISASTER_SECTION_PREFIX "disaster_"
107#define ACHIEVEMENT_SECTION_PREFIX "achievement_"
108#define ACTION_ENABLER_SECTION_PREFIX "actionenabler_"
109#define MULTIPLIER_SECTION_PREFIX "multiplier_"
110
111#define check_name(name) (check_strlen(name, MAX_LEN_NAME, NULL))
112#define check_cityname(name) (check_strlen(name, MAX_LEN_CITYNAME, NULL))
113
114/* avoid re-reading files */
115static const char name_too_long[] = "Name \"%s\" too long; truncating.";
116#define MAX_SECTION_LABEL 64
117#define section_strlcpy(dst, src) \
118 (void) loud_strlcpy(dst, src, MAX_SECTION_LABEL, name_too_long)
119static char *resource_sections = NULL;
120static char *terrain_sections = NULL;
121static char *extra_sections = NULL;
122static char *base_sections = NULL;
123static char *road_sections = NULL;
124
125static struct requirement_vector reqs_list;
126
127static bool load_rulesetdir(const char *rsdir, bool compat_mode,
129 bool act, bool buffer_script, bool load_luadata);
130static struct section_file *openload_ruleset_file(const char *whichset,
131 const char *rsdir);
132
133static bool load_game_names(struct section_file *file,
134 struct rscompat_info *compat);
135static bool load_tech_names(struct section_file *file,
136 struct rscompat_info *compat);
137static bool load_unit_names(struct section_file *file,
138 struct rscompat_info *compat);
139static bool load_building_names(struct section_file *file,
140 struct rscompat_info *compat);
141static bool load_government_names(struct section_file *file,
142 struct rscompat_info *compat);
143static bool load_terrain_names(struct section_file *file,
144 struct rscompat_info *compat);
145static bool load_style_names(struct section_file *file,
146 struct rscompat_info *compat);
147static bool load_nation_names(struct section_file *file,
148 struct rscompat_info *compat);
149static bool load_city_name_list(struct section_file *file,
150 struct nation_type *pnation,
151 const char *secfile_str1,
152 const char *secfile_str2,
153 const char **allowed_terrains,
154 size_t atcount);
155
156static bool load_ruleset_techs(struct section_file *file,
157 struct rscompat_info *compat);
158static bool load_ruleset_units(struct section_file *file,
159 struct rscompat_info *compat);
160static bool load_ruleset_buildings(struct section_file *file,
161 struct rscompat_info *compat);
162static bool load_ruleset_governments(struct section_file *file,
163 struct rscompat_info *compat);
164static bool load_ruleset_terrain(struct section_file *file,
165 struct rscompat_info *compat);
166static bool load_ruleset_styles(struct section_file *file,
167 struct rscompat_info *compat);
168static bool load_ruleset_cities(struct section_file *file,
169 struct rscompat_info *compat);
170static bool load_ruleset_effects(struct section_file *file,
171 struct rscompat_info *compat);
172static bool load_ruleset_game(struct section_file *file, bool act,
173 struct rscompat_info *compat);
174
175static void send_ruleset_tech_classes(struct conn_list *dest);
176static void send_ruleset_techs(struct conn_list *dest);
177static void send_ruleset_unit_classes(struct conn_list *dest);
178static void send_ruleset_units(struct conn_list *dest);
179static void send_ruleset_buildings(struct conn_list *dest);
180static void send_ruleset_terrain(struct conn_list *dest);
181static void send_ruleset_resources(struct conn_list *dest);
182static void send_ruleset_extras(struct conn_list *dest);
183static void send_ruleset_bases(struct conn_list *dest);
184static void send_ruleset_roads(struct conn_list *dest);
185static void send_ruleset_goods(struct conn_list *dest);
186static void send_ruleset_governments(struct conn_list *dest);
187static void send_ruleset_styles(struct conn_list *dest);
188static void send_ruleset_clauses(struct conn_list *dest);
189static void send_ruleset_musics(struct conn_list *dest);
190static void send_ruleset_cities(struct conn_list *dest);
191static void send_ruleset_game(struct conn_list *dest);
192static void send_ruleset_team_names(struct conn_list *dest);
193
194static bool load_ruleset_veteran(struct section_file *file,
195 const char *path,
196 struct veteran_system **vsystem, char *err,
197 size_t err_len, struct rscompat_info *compat);
198
199char *script_buffer = NULL;
200char *parser_buffer = NULL;
201
202/**********************************************************************/
207 const char *file, const char *function,
208 int line, enum log_level level,
209 const char *format, ...)
210{
211 va_list args;
212 char buf[MAX_LEN_LOG_LINE];
213
214 if (logger == NULL && !log_do_output_for_level(level)) {
215 return;
216 }
217
218 va_start(args, format);
219 if (logger != NULL) {
220 fc_vsnprintf(buf, sizeof(buf), format, args);
221 logger(buf);
222 } else {
223 vdo_log(file, function, line, FALSE, level, buf, sizeof(buf), format, args);
224 }
225 va_end(args);
226
227 if (LOG_FATAL >= level) {
228 exit(EXIT_FAILURE);
229 }
230}
231
232/**********************************************************************/
236{
237 int purged = 0;
238
239 action_iterate(act_id) {
240 struct action *paction = action_by_number(act_id);
241
242 if (action_enabler_list_size(action_enablers_for_action(paction->id))
243 == 0) {
244 /* Not relevant. */
245 continue;
246 }
247
248 /* Impossible hard requirement. */
249 if (!action_is_in_use(paction)) {
250 /* Make sure that all action enablers are disabled. */
252 ae) {
253 ae->ruledit_disabled = TRUE;
254 purged++;
256
257 log_normal("Purged all action enablers for %s",
258 action_rule_name(paction));
259 }
260
261 /* Impossible requirement vector requirement. */
263 ae) {
264 if (!ae->ruledit_disabled
266 || req_vec_is_impossible_to_fulfill(&ae->target_reqs))) {
267 ae->ruledit_disabled = TRUE;
268 purged++;
269 log_normal("Purged unused action enabler for %s",
270 action_rule_name(paction));
271 }
274
275 return purged;
276}
277
278/**********************************************************************/
282{
283 int purged = 0;
284 enum effect_type type;
285
286 for (type = effect_type_begin(); type != effect_type_end();
287 type = effect_type_next(type)) {
289 if (req_vec_is_impossible_to_fulfill(&eft->reqs)) {
290 eft->ruledit_do_not_save = TRUE;
291 purged++;
292 log_normal("Purged unused effect for %s",
293 effect_type_name(eft->type));
294 }
296 }
297
298 return purged;
299}
300
301/**********************************************************************/
305{
306 int purged = 0;
307
310
311 return purged;
312}
313
314/**********************************************************************/
318static bool purge_unused_req_vec(const struct requirement_vector *reqs,
319 const char *msg)
320{
321 struct req_vec_problem *problem;
322 bool result;
323
325 reqs);
326
327 if (problem == NULL) {
328 /* No problem. */
329 return FALSE;
330 }
331
332 if (problem->num_suggested_solutions == 0) {
333 /* No solution. */
334 req_vec_problem_free(problem);
335 return FALSE;
336 }
337
338 if (problem->num_suggested_solutions == 1
339 && problem->suggested_solutions[0].operation == RVCO_REMOVE) {
340 /* Remove !present req that never is there. */
341 log_normal("%s", msg);
342 result = req_vec_change_apply(&problem->suggested_solutions[0],
344 req_vec_problem_free(problem);
345 return result;
346 }
347
348 /* Not handled. Don't know what this is. */
349 fc_assert(problem->num_suggested_solutions == 1);
350 req_vec_problem_free(problem);
351 return FALSE;
352}
353
354/**********************************************************************/
358static bool purge_duplicate_req_vec(const struct requirement_vector *reqs,
359 const char *msg)
360{
361 struct req_vec_problem *problem;
362 bool result;
363
365 reqs);
366
367 if (problem == NULL) {
368 /* No problem. */
369 return FALSE;
370 }
371
372 if (problem->num_suggested_solutions == 0) {
373 /* No solution. */
374 req_vec_problem_free(problem);
375 return FALSE;
376 }
377
378 if (problem->num_suggested_solutions == 2
379 && problem->suggested_solutions[0].operation == RVCO_REMOVE
380 && problem->suggested_solutions[1].operation == RVCO_REMOVE
382 &problem->suggested_solutions[1].req)) {
383 /* Simple duplication is handled. */
384 log_normal("%s", msg);
385 result = req_vec_change_apply(&problem->suggested_solutions[1],
387 req_vec_problem_free(problem);
388 return result;
389 }
390
391 /* Requirements of different kinds making each other redundant isn't
392 * supported yet. It could be done by always removing the most general
393 * requirement. So unit type is kept when redundant with unit flag, unit
394 * class and unit class flag etc. */
395 req_vec_problem_free(problem);
396 return FALSE;
397}
398
399/**********************************************************************/
403static bool purge_redundant_req_vec(const struct requirement_vector *reqs,
404 const char *msg)
405{
406 return (purge_unused_req_vec(reqs, msg)
408}
409
410/**********************************************************************/
415{
416 int purged = 0;
417
418 action_iterate(act_id) {
419 struct action *paction = action_by_number(act_id);
420 char actor_reqs[MAX_LEN_NAME * 2];
421 char target_reqs[MAX_LEN_NAME * 2];
422
423 /* Error log text */
424 fc_snprintf(actor_reqs, sizeof(actor_reqs),
425 "Purged redundant requirement in"
426 " %s in action enabler for %s",
427 "actor_reqs", action_rule_name(paction));
428 fc_snprintf(target_reqs, sizeof(target_reqs),
429 "Purged redundant requirement in"
430 " %s in action enabler for %s",
431 "target_reqs", action_rule_name(paction));
432
433 /* Do the purging. */
435 ae) {
436 while (!ae->ruledit_disabled
437 && (purge_redundant_req_vec(&ae->actor_reqs, actor_reqs)
438 || purge_redundant_req_vec(&ae->target_reqs,
439 target_reqs))) {
440 purged++;
441 }
444
445 return purged;
446}
447
448/**********************************************************************/
453{
454 int purged = 0;
455 enum effect_type type;
456
457 for (type = effect_type_begin(); type != effect_type_end();
458 type = effect_type_next(type)) {
459 char msg[MAX_LEN_NAME * 2];
460
461 /* Error log text */
462 fc_snprintf(msg, sizeof(msg),
463 "Purged redundant requirement in effect of type %s",
464 effect_type_name(type));
465
466 /* Do the purging. */
468 while (purge_redundant_req_vec(&eft->reqs, msg)) {
469 purged++;
470 }
472 }
473
474 return purged;
475}
476
477/**********************************************************************/
482{
483 int purged = 0;
484
487
488 if (purged > 0) {
489 /* An unused requirement may be an obligatory hard requirement. */
491 }
492
493 return purged;
494}
495
496/**********************************************************************/
500static const char *valid_ruleset_filename(const char *subdir,
501 const char *name,
502 const char *extension,
503 bool optional)
504{
505 char filename[512];
506 const char *dfilename;
507
508 fc_assert_ret_val(subdir && name && extension, NULL);
509
510 fc_snprintf(filename, sizeof(filename), "%s" DIR_SEPARATOR "%s.%s",
511 subdir, name, extension);
512 log_verbose("Trying \"%s\".", filename);
513 dfilename = fileinfoname(get_data_dirs(), filename);
514 if (dfilename) {
515 return dfilename;
516 }
517
518 fc_snprintf(filename, sizeof(filename), "default" DIR_SEPARATOR "%s.%s", name, extension);
519 log_verbose("Trying \"%s\": default ruleset directory.", filename);
520 dfilename = fileinfoname(get_data_dirs(), filename);
521 if (dfilename) {
522 return dfilename;
523 }
524
525 fc_snprintf(filename, sizeof(filename), "%s_%s.%s",
526 subdir, name, extension);
527 log_verbose("Trying \"%s\": alternative ruleset filename syntax.",
528 filename);
529 dfilename = fileinfoname(get_data_dirs(), filename);
530 if (dfilename) {
531 return dfilename;
532 } else if (!optional) {
534 /* TRANS: message about an installation error. */
535 _("Could not find a readable \"%s.%s\" ruleset file."),
536 name, extension);
537 }
538
539 return NULL;
540}
541
542/**********************************************************************/
546{
547 return script_buffer;
548}
549
550/**********************************************************************/
554{
555 return parser_buffer;
556}
557
558/**********************************************************************/
562static struct section_file *openload_ruleset_file(const char *whichset,
563 const char *rsdir)
564{
565 char sfilename[512];
566 const char *dfilename = valid_ruleset_filename(rsdir, whichset,
568 struct section_file *secfile;
569
570 if (dfilename == NULL) {
571 return NULL;
572 }
573
574 /* Need to save a copy of the filename for following message, since
575 section_file_load() may call datafilename() for includes. */
576 sz_strlcpy(sfilename, dfilename);
577 secfile = secfile_load(sfilename, FALSE);
578
579 if (secfile == NULL) {
580 ruleset_error(NULL, LOG_ERROR, "Could not load ruleset '%s':\n%s",
581 sfilename, secfile_error());
582 }
583
584 return secfile;
585}
586
587/**********************************************************************/
590static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir,
591 char **buffer, bool optional)
592{
593 const char *dfilename = valid_ruleset_filename(rsdir, whichset,
594 SCRIPT_SUFFIX, optional);
595
596 if (dfilename == NULL) {
597 return optional ? TRI_MAYBE : TRI_NO;
598 }
599
600 if (buffer == NULL) {
601 if (!script_server_do_file(NULL, dfilename)) {
602 ruleset_error(NULL, LOG_ERROR, "\"%s\": could not load ruleset script.",
603 dfilename);
604
605 return TRI_NO;
606 }
607 } else {
608 script_server_load_file(dfilename, buffer);
609 }
610
611 return TRI_YES;
612}
613
614/**********************************************************************/
617static struct section_file *openload_luadata_file(const char *rsdir)
618{
619 struct section_file *secfile;
620 char sfilename[512];
621 const char *dfilename = valid_ruleset_filename(rsdir, "luadata",
622 "txt", TRUE);
623
624 if (dfilename == NULL) {
625 return NULL;
626 }
627
628 /* Need to save a copy of the filename for following message, since
629 section_file_load() may call datafilename() for includes. */
630 sz_strlcpy(sfilename, dfilename);
631 secfile = secfile_load(sfilename, FALSE);
632
633 if (secfile == NULL) {
634 ruleset_error(NULL, LOG_ERROR, "Could not load luadata '%s':\n%s",
635 sfilename, secfile_error());
636 }
637
638 return secfile;
639}
640
641/**********************************************************************/
645struct requirement_vector *lookup_req_list(struct section_file *file,
646 struct rscompat_info *compat,
647 const char *sec,
648 const char *sub,
649 const char *rfor)
650{
651 const char *type, *name;
652 int j;
653 const char *filename;
654
655 filename = secfile_name(file);
656
657 requirement_vector_reserve(&reqs_list, 0);
658
659 for (j = 0; (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
660 sec, sub, j)); j++) {
661 char buf[MAX_LEN_NAME];
662 const char *range;
663 bool survives, present, quiet;
664 struct entry *pentry;
665 struct requirement req;
666
667 if (compat->compat_mode) {
669 }
670
671 if (!(pentry = secfile_entry_lookup(file, "%s.%s%d.name",
672 sec, sub, j))) {
673 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
674
675 return NULL;
676 }
677 name = NULL;
678 switch (entry_type_get(pentry)) {
679 case ENTRY_BOOL:
680 {
681 bool val;
682
683 if (entry_bool_get(pentry, &val)) {
684 fc_snprintf(buf, sizeof(buf), "%d", val);
685 name = buf;
686 }
687 }
688 break;
689 case ENTRY_INT:
690 {
691 int val;
692
693 if (entry_int_get(pentry, &val)) {
694 fc_snprintf(buf, sizeof(buf), "%d", val);
695 name = buf;
696 }
697 }
698 break;
699 case ENTRY_STR:
700 (void) entry_str_get(pentry, &name);
701 break;
702 case ENTRY_FLOAT:
705 "\"%s\": trying to have an floating point entry as a requirement name in '%s.%s%d'.",
706 filename, sec, sub, j);
707 break;
710 break;
711 case ENTRY_ILLEGAL:
713 break;
714 }
715 if (NULL == name) {
717 "\"%s\": error in handling requirement name for '%s.%s%d'.",
718 filename, sec, sub, j);
719 return NULL;
720 }
721
722 if (!(range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j))) {
723 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
724
725 return NULL;
726 }
727
728 survives = FALSE;
729 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.survives",
730 sec, sub, j))
731 && !entry_bool_get(pentry, &survives)) {
733 "\"%s\": invalid boolean value for survives for "
734 "'%s.%s%d'.", filename, sec, sub, j);
735 }
736
737 present = TRUE;
738 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.present",
739 sec, sub, j))
740 && !entry_bool_get(pentry, &present)) {
742 "\"%s\": invalid boolean value for present for "
743 "'%s.%s%d'.", filename, sec, sub, j);
744 }
745 quiet = FALSE;
746 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.quiet",
747 sec, sub, j))
748 && !entry_bool_get(pentry, &quiet)) {
750 "\"%s\": invalid boolean value for quiet for "
751 "'%s.%s%d'.", filename, sec, sub, j);
752 }
753
754 if (compat->compat_mode) {
755 if (!fc_strcasecmp(type, universals_n_name(VUT_UTFLAG))) {
757 }
758 }
759
760 if (compat->compat_mode) {
762 }
763
764 if (compat->compat_mode) {
765 if (!fc_strcasecmp(type, "UnitState")
766 && !fc_strcasecmp(name, "OnDomesticTile")) {
767 type = "DiplRelTile";
768 name = "Foreign";
769 present = !present;
770 }
771 }
772
774 if (req.source.kind == universals_n_invalid()) {
776 "\"%s\" [%s] has invalid or unknown req: "
777 "\"%s\" \"%s\".",
778 filename, sec, type, name);
779
780 return NULL;
781 }
782
783 requirement_vector_append(&reqs_list, req);
784 }
785
786 if (compat->compat_mode) {
788 filename, sec, sub, rfor);
789 }
790
791 if (j > MAX_NUM_REQS) {
793 "Too many (%d) requirements for %s. Max is %d",
794 j, rfor, MAX_NUM_REQS);
795
796 return NULL;
797 }
798
799 return &reqs_list;
800}
801
802/**********************************************************************/
806 struct combat_bonus_list *list,
807 struct section_file *file,
808 const char *sec,
809 const char *sub)
810{
811 const char *flag;
812 int j;
813 const char *filename;
814 bool success = TRUE;
815
816 filename = secfile_name(file);
817
818 for (j = 0; (flag = secfile_lookup_str_default(file, NULL, "%s.%s%d.flag",
819 sec, sub, j)); j++) {
820 struct combat_bonus *bonus = fc_malloc(sizeof(*bonus));
821 const char *type;
822
823 bonus->flag = unit_type_flag_id_by_name(rscompat_utype_flag_name_3_1(compat, flag),
825 if (!unit_type_flag_id_is_valid(bonus->flag)) {
826 log_error("\"%s\": unknown flag name \"%s\" in '%s.%s'.",
827 filename, flag, sec, sub);
828 FC_FREE(bonus);
829 success = FALSE;
830 continue;
831 }
832 type = secfile_lookup_str(file, "%s.%s%d.type", sec, sub, j);
834 bonus->type = combat_bonus_type_by_name(type, fc_strcasecmp);
835 if (!combat_bonus_type_is_valid(bonus->type)) {
836 log_error("\"%s\": unknown bonus type \"%s\" in '%s.%s'.",
837 filename, type, sec, sub);
838 FC_FREE(bonus);
839 success = FALSE;
840 continue;
841 }
842 if (!secfile_lookup_int(file, &bonus->value, "%s.%s%d.value",
843 sec, sub, j)) {
844 log_error("\"%s\": failed to get value from '%s.%s%d'.",
845 filename, sec, sub, j);
846 FC_FREE(bonus);
847 success = FALSE;
848 continue;
849 }
851 "%s.%s%d.quiet",
852 sec, sub, j);
853 combat_bonus_list_append(list, bonus);
854 }
855
856 return success;
857}
858
859/**********************************************************************/
867static bool lookup_tech(struct section_file *file,
868 struct advance **result,
869 const char *prefix, const char *entry,
870 const char *filename,
871 const char *description)
872{
873 const char *sval;
874
875 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
876 if (!sval || !strcmp(sval, "Never")) {
877 *result = A_NEVER;
878 } else {
879 *result = advance_by_rule_name(sval);
880
881 if (A_NEVER == *result) {
883 "\"%s\" %s %s: couldn't match \"%s\".",
884 filename, (description ? description : prefix), entry, sval);
885 return FALSE;
886 }
887 }
888
889 return TRUE;
890}
891
892/**********************************************************************/
899static bool lookup_building(struct section_file *file,
900 const char *prefix, const char *entry,
901 struct impr_type **result,
902 const char *filename,
903 const char *description)
904{
905 const char *sval;
906 bool ok = TRUE;
907
908 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
909 if (!sval || strcmp(sval, "None") == 0) {
910 *result = B_NEVER;
911 } else {
912 *result = improvement_by_rule_name(sval);
913
914 if (B_NEVER == *result) {
916 "\"%s\" %s %s: couldn't match \"%s\".",
917 filename, (description ? description : prefix), entry, sval);
918 ok = FALSE;
919 }
920 }
921
922 return ok;
923}
924
925/**********************************************************************/
932static bool lookup_unit_list(struct section_file *file, const char *prefix,
933 const char *entry,
934 struct unit_type **output,
935 const char *filename)
936{
937 const char **slist;
938 size_t nval;
939 int i;
940 bool ok = TRUE;
941
942 /* pre-fill with NULL: */
943 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
944 output[i] = NULL;
945 }
946 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
947 if (nval == 0) {
948 /* 'No vector' is considered same as empty vector */
949 if (slist != NULL) {
950 free(slist);
951 }
952 return TRUE;
953 }
954 if (nval > MAX_NUM_UNIT_LIST) {
956 "\"%s\": string vector %s.%s too long (%d, max %d)",
957 filename, prefix, entry, (int) nval, MAX_NUM_UNIT_LIST);
958 ok = FALSE;
959 } else if (nval == 1 && strcmp(slist[0], "") == 0) {
960 free(slist);
961 return TRUE;
962 }
963 if (ok) {
964 for (i = 0; i < nval; i++) {
965 const char *sval = slist[i];
966 struct unit_type *punittype = unit_type_by_rule_name(sval);
967
968 if (!punittype) {
970 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
971 filename, prefix, entry, i, sval);
972 ok = FALSE;
973 break;
974 }
975 output[i] = punittype;
976 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
977 utype_number(punittype));
978 }
979 }
980 free(slist);
981
982 return ok;
983}
984
985/**********************************************************************/
992static bool lookup_tech_list(struct section_file *file, const char *prefix,
993 const char *entry, int *output,
994 const char *filename)
995{
996 const char **slist;
997 size_t nval;
998 int i;
999 bool ok = TRUE;
1000
1001 /* pre-fill with A_LAST: */
1002 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
1003 output[i] = A_LAST;
1004 }
1005 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
1006 if (slist == NULL || nval == 0) {
1007 return TRUE;
1008 } else if (nval > MAX_NUM_TECH_LIST) {
1010 "\"%s\": string vector %s.%s too long (%d, max %d)",
1011 filename, prefix, entry, (int) nval, MAX_NUM_TECH_LIST);
1012 ok = FALSE;
1013 }
1014
1015 if (ok) {
1016 if (nval == 1 && strcmp(slist[0], "") == 0) {
1017 FC_FREE(slist);
1018 return TRUE;
1019 }
1020 for (i = 0; i < nval && ok; i++) {
1021 const char *sval = slist[i];
1022 struct advance *padvance = advance_by_rule_name(sval);
1023
1024 if (NULL == padvance) {
1026 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1027 filename, prefix, entry, i, sval);
1028 ok = FALSE;
1029 }
1030 if (!valid_advance(padvance)) {
1032 "\"%s\" %s.%s (%d): \"%s\" is removed.",
1033 filename, prefix, entry, i, sval);
1034 ok = FALSE;
1035 }
1036
1037 if (ok) {
1038 output[i] = advance_number(padvance);
1039 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
1040 advance_number(padvance));
1041 }
1042 }
1043 }
1044 FC_FREE(slist);
1045
1046 return ok;
1047}
1048
1049/**********************************************************************/
1056static bool lookup_building_list(struct section_file *file,
1057 const char *prefix, const char *entry,
1058 int *output, const char *filename)
1059{
1060 const char **slist;
1061 size_t nval;
1062 int i;
1063 bool ok = TRUE;
1064
1065 /* pre-fill with B_LAST: */
1066 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
1067 output[i] = B_LAST;
1068 }
1069 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
1070 if (nval > MAX_NUM_BUILDING_LIST) {
1072 "\"%s\": string vector %s.%s too long (%d, max %d)",
1073 filename, prefix, entry, (int) nval, MAX_NUM_BUILDING_LIST);
1074 ok = FALSE;
1075 } else if (nval == 0 || (nval == 1 && strcmp(slist[0], "") == 0)) {
1076 if (slist != NULL) {
1077 FC_FREE(slist);
1078 }
1079 return TRUE;
1080 }
1081 if (ok) {
1082 for (i = 0; i < nval; i++) {
1083 const char *sval = slist[i];
1084 struct impr_type *pimprove = improvement_by_rule_name(sval);
1085
1086 if (NULL == pimprove) {
1088 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1089 filename, prefix, entry, i, sval);
1090 ok = FALSE;
1091 break;
1092 }
1093 output[i] = improvement_number(pimprove);
1094 log_debug("%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
1095 }
1096 }
1097 free(slist);
1098
1099 return ok;
1100}
1101
1102/**********************************************************************/
1108static bool lookup_unit_type(struct section_file *file,
1109 const char *prefix,
1110 const char *entry,
1111 const struct unit_type **result,
1112 const char *filename,
1113 const char *description)
1114{
1115 const char *sval;
1116
1117 sval = secfile_lookup_str_default(file, "None", "%s.%s", prefix, entry);
1118
1119 if (strcmp(sval, "None") == 0) {
1120 *result = NULL;
1121 } else {
1122 *result = unit_type_by_rule_name(sval);
1123 if (*result == NULL) {
1125 "\"%s\" %s %s: couldn't match \"%s\".",
1126 filename, (description ? description : prefix), entry, sval);
1127
1128 return FALSE;
1129 }
1130 }
1131
1132 return TRUE;
1133}
1134
1135/**********************************************************************/
1139static struct government *lookup_government(struct section_file *file,
1140 const char *entry,
1141 const char *filename,
1142 struct government *fallback)
1143{
1144 const char *sval;
1145 struct government *gov;
1146
1147 sval = secfile_lookup_str_default(file, NULL, "%s", entry);
1148 if (!sval) {
1149 gov = fallback;
1150 } else {
1151 gov = government_by_rule_name(sval);
1152 }
1153 if (!gov) {
1155 "\"%s\" %s: couldn't match \"%s\".",
1156 filename, entry, sval);
1157 }
1158 return gov;
1159}
1160
1161/**********************************************************************/
1164static char *lookup_string(struct section_file *file, const char *prefix,
1165 const char *suffix)
1166{
1167 const char *sval = secfile_lookup_str(file, "%s.%s", prefix, suffix);
1168
1169 if (NULL != sval) {
1170 char copy[strlen(sval) + 1];
1171
1172 strcpy(copy, sval);
1174 if (strlen(copy) > 0) {
1175 return fc_strdup(copy);
1176 }
1177 }
1178 return NULL;
1179}
1180
1181/**********************************************************************/
1184static struct strvec *lookup_strvec(struct section_file *file,
1185 const char *prefix, const char *suffix)
1186{
1187 size_t dim;
1188 const char **vec = secfile_lookup_str_vec(file, &dim,
1189 "%s.%s", prefix, suffix);
1190
1191 if (NULL != vec) {
1192 struct strvec *dest = strvec_new();
1193
1194 strvec_store(dest, vec, dim);
1195 free(vec);
1196 return dest;
1197 }
1198 return NULL;
1199}
1200
1201/**********************************************************************/
1204static struct extra_type *lookup_resource(const char *filename,
1205 const char *name,
1206 const char *jsection)
1207{
1208 struct extra_type *pres;
1209
1211
1212 if (pres == NULL) {
1214 "\"%s\" [%s] has unknown \"%s\".",
1215 filename, jsection, name);
1216 }
1217
1218 return pres;
1219}
1220
1221/**********************************************************************/
1225static bool lookup_terrain(struct section_file *file,
1226 const char *entry,
1227 const char *filename,
1228 struct terrain *pthis,
1229 struct terrain **result,
1230 bool null_acceptable)
1231{
1232 const int j = terrain_index(pthis);
1233 const char *jsection = &terrain_sections[j * MAX_SECTION_LABEL];
1234 const char *name = secfile_lookup_str(file, "%s.%s", jsection, entry);
1235 struct terrain *pterr;
1236
1237 if (NULL == name && !null_acceptable) {
1238 return FALSE;
1239 }
1240
1241 if (NULL == name
1242 || *name == '\0'
1243 || (0 == strcmp(name, "none"))
1244 || (0 == strcmp(name, "no"))) {
1245 *result = T_NONE;
1246
1247 return TRUE;
1248 }
1249 if (0 == strcmp(name, "yes")) {
1250 *result = pthis;
1251
1252 return TRUE;
1253 }
1254
1255 pterr = terrain_by_rule_name(name);
1256 *result = pterr;
1257
1258 if (pterr == NULL) {
1260 "\"%s\" [%s] has unknown \"%s\".",
1261 secfile_name(file), jsection, name);
1262 return FALSE;
1263 }
1264
1265 return TRUE;
1266}
1267
1268/**********************************************************************/
1275static bool lookup_time(const struct section_file *secfile, int *turns,
1276 const char *sec_name, const char *property_name,
1277 const char *filename, const char *item_name,
1278 bool *ok)
1279{
1280 /* Assumes that PACKET_UNIT_INFO.activity_count in packets.def is UINT16 */
1281 const int max_turns = 65535 / ACTIVITY_FACTOR;
1282
1283 if (!secfile_lookup_int(secfile, turns, "%s.%s", sec_name, property_name)) {
1284 return FALSE;
1285 }
1286
1287 if (*turns > max_turns) {
1289 "\"%s\": \"%s\": \"%s\" value %d too large (max %d)",
1290 filename, item_name ? item_name : sec_name,
1291 property_name, *turns, max_turns);
1292 *ok = FALSE;
1293 }
1294
1295 return TRUE; /* we found _something */
1296}
1297
1298/**********************************************************************/
1301static bool ruleset_load_names(struct name_translation *pname,
1302 const char *domain,
1303 struct section_file *file,
1304 const char *sec_name)
1305{
1306 const char *name = secfile_lookup_str(file, "%s.name", sec_name);
1307 const char *rule_name = secfile_lookup_str(file, "%s.rule_name", sec_name);
1308
1309 if (!name) {
1311 "\"%s\" [%s]: no \"name\" specified.",
1312 secfile_name(file), sec_name);
1313 return FALSE;
1314 }
1315
1316 names_set(pname, domain, name, rule_name);
1317
1318 return TRUE;
1319}
1320
1321/**********************************************************************/
1324static void ruleset_load_traits(struct trait_limits *out,
1325 struct section_file *file,
1326 const char *secname, const char *field_prefix)
1327{
1328 enum trait tr;
1329
1330 /* FIXME: Use specenum trait names without duplicating them here.
1331 * Just needs to take care of case.
1332 * This list is also duplicated in rulesave.c:save_traits() */
1333 const char *trait_names[] = {
1334 "expansionist",
1335 "trader",
1336 "aggressive",
1337 "builder",
1338 NULL
1339 };
1340
1341 for (tr = trait_begin(); tr != trait_end() && trait_names[tr] != NULL; tr = trait_next(tr)) {
1342 out[tr].min = secfile_lookup_int_default(file, -1, "%s.%s%s_min",
1343 secname,
1344 field_prefix,
1345 trait_names[tr]);
1346 out[tr].max = secfile_lookup_int_default(file, -1, "%s.%s%s_max",
1347 secname,
1348 field_prefix,
1349 trait_names[tr]);
1350 out[tr].fixed = secfile_lookup_int_default(file, -1, "%s.%s%s_default",
1351 secname,
1352 field_prefix,
1353 trait_names[tr]);
1354 }
1355
1356 fc_assert(tr == trait_end()); /* number of trait_names correct */
1357}
1358
1359/**********************************************************************/
1363static bool load_game_names(struct section_file *file,
1364 struct rscompat_info *compat)
1365{
1366 struct section_list *sec;
1367 int nval;
1368 const char *filename = secfile_name(file);
1369 bool ok = TRUE;
1370
1371 /* section: datafile */
1373 if (compat->version <= 0) {
1374 return FALSE;
1375 }
1376
1377 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1378 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1379
1381 nval = (NULL != sec ? section_list_size(sec) : 0);
1382 if (nval > MAX_ACHIEVEMENT_TYPES) {
1383 int num = nval; /* No "size_t" to printf */
1384
1386 "\"%s\": Too many achievement types (%d, max %d)",
1387 filename, num, MAX_ACHIEVEMENT_TYPES);
1388 ok = FALSE;
1389 } else {
1391 }
1392
1393 if (ok) {
1394 achievements_iterate(pach) {
1395 const char *sec_name = section_name(section_list_get(sec, achievement_index(pach)));
1396
1397 if (!ruleset_load_names(&pach->name, NULL, file, sec_name)) {
1399 "\"%s\": Cannot load achievement names",
1400 filename);
1401 ok = FALSE;
1402 break;
1403 }
1405 }
1406
1407 section_list_destroy(sec);
1408
1409 if (ok) {
1411
1412 nval = (NULL != sec ? section_list_size(sec) : 0);
1413 if (nval > MAX_GOODS_TYPES) {
1414 int num = nval; /* No "size_t" to printf */
1415
1417 "\"%s\": Too many goods types (%d, max %d)",
1418 filename, num, MAX_GOODS_TYPES);
1419 section_list_destroy(sec);
1420 ok = FALSE;
1421 } else if (nval < 1) {
1423 "\"%s\": At least one goods type needed",
1424 filename);
1425 section_list_destroy(sec);
1426 ok = FALSE;
1427 } else {
1429 }
1430
1431 if (ok) {
1432 goods_type_iterate(pgood) {
1433 const char *sec_name
1434 = section_name(section_list_get(sec, goods_index(pgood)));
1435
1436 if (!ruleset_load_names(&pgood->name, NULL, file, sec_name)) {
1438 "\"%s\": Cannot load goods names",
1439 filename);
1440 ok = FALSE;
1441 break;
1442 }
1444 }
1445 section_list_destroy(sec);
1446 }
1447
1448 return ok;
1449}
1450
1451
1452/**********************************************************************/
1456static bool load_tech_names(struct section_file *file,
1457 struct rscompat_info *compat)
1458{
1459 struct section_list *sec = NULL;
1460 /* Number of techs in the ruleset (means without A_NONE). */
1461 int num_techs = 0;
1462 int i;
1463 const char *filename = secfile_name(file);
1464 bool ok = TRUE;
1465 const char *flag;
1466
1467 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1468 return FALSE;
1469 }
1470
1471 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1472 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1473
1474 /* User tech flag names */
1475 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1476 i++) {
1477 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1478 i);
1479 if (tech_flag_id_by_name(flag, fc_strcasecmp) != tech_flag_id_invalid()) {
1481 "\"%s\": Duplicate tech flag name '%s'",
1482 filename, flag);
1483 ok = FALSE;
1484 break;
1485 }
1486 if (i > MAX_NUM_USER_TECH_FLAGS) {
1488 "\"%s\": Too many user tech flags!",
1489 filename);
1490 ok = FALSE;
1491 break;
1492 }
1493
1494 set_user_tech_flag_name(TECH_USER_1 + i, flag, helptxt);
1495 }
1496
1497 if (ok) {
1498 size_t nval;
1499
1500 for (; i < MAX_NUM_USER_TECH_FLAGS; i++) {
1501 set_user_tech_flag_name(TECH_USER_1 + i, NULL, NULL);
1502 }
1503
1504 /* Tech classes */
1506
1507 nval = (NULL != sec ? section_list_size(sec) : 0);
1508 if (nval > MAX_NUM_TECH_CLASSES) {
1509 int num = nval; /* No "size_t" to printf */
1510
1512 "\"%s\": Too many tech classes (%d, max %d)",
1513 filename, num, MAX_NUM_TECH_CLASSES);
1514 section_list_destroy(sec);
1515 ok = FALSE;
1516 } else {
1518 }
1519
1520 if (ok) {
1521 tech_class_iterate(ptclass) {
1522 const char *sec_name
1523 = section_name(section_list_get(sec, tech_class_index(ptclass)));
1524
1525 if (!ruleset_load_names(&ptclass->name, NULL, file, sec_name)) {
1526 ruleset_error(NULL, LOG_ERROR, "\"%s\": Cannot load tech class names",
1527 filename);
1528 ok = FALSE;
1529 break;
1530 }
1532 }
1533 }
1534
1535 if (ok) {
1536 /* The techs: */
1538 if (NULL == sec || 0 == (num_techs = section_list_size(sec))) {
1540 "\"%s\": No Advances?!?", filename);
1541 ok = FALSE;
1542 } else {
1543 log_verbose("%d advances (including possibly unused)", num_techs);
1544 if (num_techs + A_FIRST > A_LAST) {
1546 "\"%s\": Too many advances (%d, max %d)",
1547 filename, num_techs, A_LAST - A_FIRST);
1548 ok = FALSE;
1549 }
1550 }
1551 }
1552
1553 if (ok) {
1554 game.control.num_tech_types = num_techs + A_FIRST; /* includes A_NONE */
1555
1556 i = 0;
1558 if (!ruleset_load_names(&a->name, NULL, file, section_name(section_list_get(sec, i)))) {
1559 ok = FALSE;
1560 break;
1561 }
1562 i++;
1564 }
1565 section_list_destroy(sec);
1566
1567 return ok;
1568}
1569
1570/**********************************************************************/
1573static bool load_ruleset_techs(struct section_file *file,
1574 struct rscompat_info *compat)
1575{
1576 struct section_list *sec;
1577 const char **slist;
1578 int i;
1579 size_t nval;
1580 struct advance *a_none = advance_by_number(A_NONE);
1581 const char *filename = secfile_name(file);
1582 bool ok = TRUE;
1583
1585
1586 i = 0;
1587 tech_class_iterate(ptclass) {
1588 const char *sec_name = section_name(section_list_get(sec, i));
1589
1590 ptclass->cost_pct = secfile_lookup_int_default(file, 100, "%s.%s",
1591 sec_name, "cost_pct");
1592
1593 i++;
1595
1597
1598 i = 0;
1600 const char *sec_name = section_name(section_list_get(sec, i));
1601 const char *sval;
1602 int j, ival;
1603 struct requirement_vector *research_reqs;
1604
1605 if (!lookup_tech(file, &a->require[AR_ONE], sec_name, "req1",
1606 filename, rule_name_get(&a->name))
1607 || !lookup_tech(file, &a->require[AR_TWO], sec_name, "req2",
1608 filename, rule_name_get(&a->name))
1609 || !lookup_tech(file, &a->require[AR_ROOT], sec_name, "root_req",
1610 filename, rule_name_get(&a->name))) {
1611 ok = FALSE;
1612 break;
1613 }
1614
1615 if ((A_NEVER == a->require[AR_ONE] && A_NEVER != a->require[AR_TWO])
1616 || (A_NEVER != a->require[AR_ONE] && A_NEVER == a->require[AR_TWO])) {
1618 "\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
1619 filename, sec_name, rule_name_get(&a->name));
1620 ok = FALSE;
1621 break;
1622 }
1623 if (a_none == a->require[AR_ONE] && a_none != a->require[AR_TWO]) {
1625 "\"%s\" [%s] \"%s\": should have \"None\" second.",
1626 filename, sec_name, rule_name_get(&a->name));
1627 ok = FALSE;
1628 break;
1629 }
1630
1631 if (game.control.num_tech_classes == 0) {
1632 a->tclass = NULL;
1633 } else {
1634 const char *classname;
1635
1636 classname = lookup_string(file, sec_name, "class");
1637 if (classname != NULL) {
1638 classname = Q_(classname);
1639 a->tclass = tech_class_by_rule_name(classname);
1640 if (a->tclass == NULL) {
1642 "\"%s\" [%s] \"%s\": Unknown tech class \"%s\".",
1643 filename, sec_name, rule_name_get(&a->name), classname);
1644 ok = FALSE;
1645 break;
1646 }
1647 } else {
1648 a->tclass = NULL; /* Default */
1649 }
1650 }
1651
1652 research_reqs = lookup_req_list(file, compat, sec_name, "research_reqs",
1653 rule_name_get(&a->name));
1654 if (research_reqs == NULL) {
1655 ok = FALSE;
1656 break;
1657 }
1658
1659 requirement_vector_copy(&a->research_reqs, research_reqs);
1660
1661 BV_CLR_ALL(a->flags);
1662
1663 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
1664 for (j = 0; j < nval; j++) {
1665 sval = slist[j];
1666 if (strcmp(sval, "") == 0) {
1667 continue;
1668 }
1669 ival = tech_flag_id_by_name(sval, fc_strcasecmp);
1670 if (!tech_flag_id_is_valid(ival)) {
1672 "\"%s\" [%s] \"%s\": bad flag name \"%s\".",
1673 filename, sec_name, rule_name_get(&a->name), sval);
1674 ok = FALSE;
1675 break;
1676 } else {
1677 BV_SET(a->flags, ival);
1678 }
1679 }
1680 free(slist);
1681
1682 if (!ok) {
1683 break;
1684 }
1685
1686 sz_strlcpy(a->graphic_str,
1687 secfile_lookup_str_default(file, "-", "%s.graphic", sec_name));
1688 sz_strlcpy(a->graphic_alt,
1690 "%s.graphic_alt", sec_name));
1691
1692 a->helptext = lookup_strvec(file, sec_name, "helptext");
1693 a->bonus_message = lookup_string(file, sec_name, "bonus_message");
1694 a->cost = secfile_lookup_int_default(file, -1, "%s.%s",
1695 sec_name, "cost");
1696 a->num_reqs = 0;
1697
1698 i++;
1700
1701 /* Propagate a root tech up into the tech tree. If a technology
1702 * X has Y has a root tech, then any technology requiring X (in the
1703 * normal way or as a root tech) also has Y as a root tech.
1704 * Later techs may gain a whole set of root techs in this way. The one
1705 * we store in AR_ROOT is a more or less arbitrary one of these,
1706 * also signalling that the set is non-empty; after this, you'll still
1707 * have to walk the tech tree to find them all. */
1708restart:
1709
1710 if (ok) {
1712 if (valid_advance(a)
1713 && A_NEVER != a->require[AR_ROOT]) {
1714 bool out_of_order = FALSE;
1715
1716 /* Now find any tech depending on this technology and update its
1717 * root_req. */
1719 if (valid_advance(b)
1720 && A_NEVER == b->require[AR_ROOT]
1721 && (a == b->require[AR_ONE] || a == b->require[AR_TWO])) {
1722 b->require[AR_ROOT] = a->require[AR_ROOT];
1723 b->inherited_root_req = TRUE;
1724 if (b < a) {
1725 out_of_order = TRUE;
1726 }
1727 }
1729
1730 if (out_of_order) {
1731 /* HACK: If we just changed the root_tech of a lower-numbered
1732 * technology, we need to go back so that we can propagate the
1733 * root_tech up to that technology's parents... */
1734 goto restart;
1735 }
1736 }
1738
1739 /* Now rename A_NEVER to A_NONE for consistency */
1741 if (A_NEVER == a->require[AR_ROOT]) {
1742 a->require[AR_ROOT] = a_none;
1743 }
1745
1746 /* Some more consistency checking:
1747 Non-removed techs depending on removed techs is too
1748 broken to fix by default, so die.
1749 */
1751 if (valid_advance(a)) {
1752 /* We check for recursive tech loops later,
1753 * in build_required_techs_helper. */
1754 if (!valid_advance(a->require[AR_ONE])) {
1756 "\"%s\" tech \"%s\": req1 leads to removed tech.",
1757 filename, advance_rule_name(a));
1758 ok = FALSE;
1759 break;
1760 }
1761 if (!valid_advance(a->require[AR_TWO])) {
1763 "\"%s\" tech \"%s\": req2 leads to removed tech.",
1764 filename, advance_rule_name(a));
1765 ok = FALSE;
1766 break;
1767 }
1768 }
1770 }
1771
1772 section_list_destroy(sec);
1773 if (ok) {
1775 }
1776
1777 return ok;
1778}
1779
1780/**********************************************************************/
1784static bool load_unit_names(struct section_file *file,
1785 struct rscompat_info *compat)
1786{
1787 struct section_list *sec = NULL;
1788 int nval = 0;
1789 int i;
1790 const char *filename = secfile_name(file);
1791 const char *flag;
1792 bool ok = TRUE;
1793
1794 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1795 return FALSE;
1796 }
1797
1798 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1799 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1800
1801 /* User unit flag names */
1802 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1803 i++) {
1804 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1805 i);
1806
1807 if (unit_type_flag_id_by_name(rscompat_utype_flag_name_3_1(compat, flag),
1809 != unit_type_flag_id_invalid()) {
1811 "\"%s\": Duplicate unit flag name '%s'",
1812 filename, flag);
1813 ok = FALSE;
1814 break;
1815 }
1816 if (i > MAX_NUM_USER_UNIT_FLAGS) {
1818 "\"%s\": Too many user unit type flags!",
1819 filename);
1820 ok = FALSE;
1821 break;
1822 }
1823
1824 set_user_unit_type_flag_name(UTYF_USER_FLAG_1 + i, flag, helptxt);
1825 }
1826
1827 if (ok) {
1828 /* Blank the remaining unit type user flags. */
1829 for (; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
1830 set_user_unit_type_flag_name(UTYF_USER_FLAG_1 + i, NULL, NULL);
1831 }
1832 }
1833
1834 if (ok) {
1835 /* User unit class flag names */
1836 for (i = 0;
1837 (flag = secfile_lookup_str_default(file, NULL,
1838 "control.class_flags%d.name",
1839 i));
1840 i++) {
1841 const char *helptxt = secfile_lookup_str_default(file, NULL,
1842 "control.class_flags%d.helptxt", i);
1843
1844 if (unit_class_flag_id_by_name(flag, fc_strcasecmp)
1845 != unit_class_flag_id_invalid()) {
1847 "\"%s\": Duplicate unit class flag name '%s'",
1848 filename, flag);
1849 ok = FALSE;
1850 break;
1851 }
1852 if (i > MAX_NUM_USER_UCLASS_FLAGS) {
1854 "\"%s\": Too many user unit class flags!",
1855 filename);
1856 ok = FALSE;
1857 break;
1858 }
1859
1860 set_user_unit_class_flag_name(UCF_USER_FLAG_1 + i, flag, helptxt);
1861 }
1862 }
1863
1864 if (ok) {
1865 /* Blank the remaining unit class user flags. */
1866 for (; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
1867 set_user_unit_class_flag_name(UCF_USER_FLAG_1 + i, NULL, NULL);
1868 }
1869 }
1870
1871 if (ok) {
1872 /* Unit classes */
1874 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1876 "\"%s\": No unit classes?!?", filename);
1877 ok = FALSE;
1878 } else {
1879 log_verbose("%d unit classes", nval);
1880 if (nval > UCL_LAST) {
1882 "\"%s\": Too many unit classes (%d, max %d)",
1883 filename, nval, UCL_LAST);
1884 ok = FALSE;
1885 }
1886 }
1887 }
1888
1889 if (ok) {
1891
1892 unit_class_iterate(punitclass) {
1893 const int pci = uclass_index(punitclass);
1894
1895 if (!ruleset_load_names(&punitclass->name, NULL, file,
1896 section_name(section_list_get(sec, pci)))) {
1897 ok = FALSE;
1898 break;
1899 }
1901 }
1902 section_list_destroy(sec);
1903 sec = NULL;
1904
1905 /* The names: */
1906 if (ok) {
1908 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1910 "\"%s\": No unit types?!?", filename);
1911 ok = FALSE;
1912 } else {
1913 log_verbose("%d unit types (including possibly unused)", nval);
1914 if (nval > U_LAST) {
1916 "\"%s\": Too many unit types (%d, max %d)",
1917 filename, nval, U_LAST);
1918 ok = FALSE;
1919 }
1920 }
1921 }
1922
1923 if (ok) {
1925
1926 unit_type_iterate(punittype) {
1927 const int utypei = utype_index(punittype);
1928 if (!ruleset_load_names(&punittype->name, NULL, file,
1929 section_name(section_list_get(sec, utypei)))) {
1930 ok = FALSE;
1931 break;
1932 }
1934 }
1935 section_list_destroy(sec);
1936
1937 return ok;
1938}
1939
1940/**********************************************************************/
1943static bool load_ruleset_veteran(struct section_file *file,
1944 const char *path,
1945 struct veteran_system **vsystem, char *err,
1946 size_t err_len, struct rscompat_info *compat)
1947{
1948 const char **vlist_name;
1949 int *vlist_power, *vlist_raise, *vlist_wraise, *vlist_move;
1950 size_t count_name, count_power, count_raise, count_wraise, count_move;
1951 int i;
1952 bool ret = TRUE;
1953
1954 /* The pointer should be uninitialised. */
1955 if (*vsystem != NULL) {
1956 fc_snprintf(err, err_len, "Veteran system is defined?!");
1957 return FALSE;
1958 }
1959
1960 /* Load data. */
1961 vlist_name = secfile_lookup_str_vec(file, &count_name,
1962 "%s.veteran_names", path);
1963 vlist_power = secfile_lookup_int_vec(file, &count_power,
1964 "%s.veteran_power_fact", path);
1965 vlist_raise = secfile_lookup_int_vec(file, &count_raise,
1966 "%s.veteran_base_raise_chance", path);
1967 if (vlist_raise == NULL) {
1968 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
1969 vlist_raise = secfile_lookup_int_vec(file, &count_raise,
1970 "%s.veteran_raise_chance", path);
1971 } else {
1972 fc_assert(count_raise == 0); /* Should be so from an attempt to
1973 * read veteran_base_raise_chance */
1974 count_raise = 0; /* ...but clang analyzer doesn't see it, or
1975 * sees something I don't. */
1976 }
1977 }
1978 vlist_wraise = secfile_lookup_int_vec(file, &count_wraise,
1979 "%s.veteran_work_raise_chance",
1980 path);
1981 vlist_move = secfile_lookup_int_vec(file, &count_move,
1982 "%s.veteran_move_bonus", path);
1983
1984 if (count_name > MAX_VET_LEVELS) {
1985 ret = FALSE;
1986 fc_snprintf(err, err_len, "\"%s\": Too many veteran levels (section "
1987 "'%s': %lu, max %d)", secfile_name(file), path,
1988 (long unsigned)count_name, MAX_VET_LEVELS);
1989 } else if (count_name != count_power
1990 || count_name != count_raise
1991 || count_name != count_wraise
1992 || count_name != count_move) {
1993 ret = FALSE;
1994 fc_snprintf(err, err_len, "\"%s\": Different lengths for the veteran "
1995 "settings in section '%s'", secfile_name(file),
1996 path);
1997 } else if (count_name == 0) {
1998 /* Nothing defined. */
1999 *vsystem = NULL;
2000 } else {
2001 /* Generate the veteran system. */
2002 *vsystem = veteran_system_new((int)count_name);
2003
2004#define rs_sanity_veteran(_path, _entry, _i, _condition, _action) \
2005 if (_condition) { \
2006 log_error("Invalid veteran definition '%s.%s[%d]'!", \
2007 _path, _entry, _i); \
2008 log_debug("Failed check: '%s'. Update value: '%s'.", \
2009 #_condition, #_action); \
2010 _action; \
2011 }
2012 for (i = 0; i < count_name; i++) {
2013 /* Some sanity checks. */
2014 rs_sanity_veteran(path, "veteran_power_fact", i,
2015 (vlist_power[i] < 0), vlist_power[i] = 0);
2016 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2017 (vlist_raise[i] < 0), vlist_raise[i] = 0);
2018 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2019 (vlist_wraise[i] < 0), vlist_wraise[i] = 0);
2020 rs_sanity_veteran(path, "veteran_move_bonus", i,
2021 (vlist_move[i] < 0), vlist_move[i] = 0);
2022 if (i == 0) {
2023 /* First element.*/
2024 rs_sanity_veteran(path, "veteran_power_fact", i,
2025 (vlist_power[i] != 100), vlist_power[i] = 100);
2026 } else if (i == count_name - 1) {
2027 /* Last element. */
2028 rs_sanity_veteran(path, "veteran_power_fact", i,
2029 (vlist_power[i] < vlist_power[i - 1]),
2030 vlist_power[i] = vlist_power[i - 1]);
2031 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2032 (vlist_raise[i] != 0), vlist_raise[i] = 0);
2033 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2034 (vlist_wraise[i] != 0), vlist_wraise[i] = 0);
2035 } else {
2036 /* All elements inbetween. */
2037 rs_sanity_veteran(path, "veteran_power_fact", i,
2038 (vlist_power[i] < vlist_power[i - 1]),
2039 vlist_power[i] = vlist_power[i - 1]);
2040 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2041 (vlist_raise[i] > 100), vlist_raise[i] = 100);
2042 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2043 (vlist_wraise[i] > 100), vlist_wraise[i] = 100);
2044 }
2045
2046 veteran_system_definition(*vsystem, i, vlist_name[i], vlist_power[i],
2047 vlist_move[i], vlist_raise[i],
2048 vlist_wraise[i]);
2049 }
2050#undef rs_sanity_veteran
2051 }
2052
2053 if (vlist_name) {
2054 free(vlist_name);
2055 }
2056 if (vlist_power) {
2057 free(vlist_power);
2058 }
2059 if (vlist_raise) {
2060 free(vlist_raise);
2061 }
2062 if (vlist_wraise) {
2063 free(vlist_wraise);
2064 }
2065 if (vlist_move) {
2066 free(vlist_move);
2067 }
2068
2069 return ret;
2070}
2071
2072/**********************************************************************/
2075static bool load_ruleset_units(struct section_file *file,
2076 struct rscompat_info *compat)
2077{
2078 int j, ival;
2079 size_t nval;
2080 struct section_list *sec, *csec;
2081 const char *sval, **slist;
2082 const char *filename = secfile_name(file);
2083 char msg[MAX_LEN_MSG];
2084 bool ok = TRUE;
2085
2086 if (!load_ruleset_veteran(file, "veteran_system", &game.veteran, msg,
2087 sizeof(msg), compat)
2088 || game.veteran == NULL) {
2090 "Error loading the default veteran system: %s",
2091 msg);
2092 ok = FALSE;
2093 }
2094
2096 nval = (NULL != sec ? section_list_size(sec) : 0);
2097
2099 nval = (NULL != csec ? section_list_size(csec) : 0);
2100
2101 if (ok) {
2102 unit_class_iterate(uc) {
2103 int i = uclass_index(uc);
2104 const char *sec_name = section_name(section_list_get(csec, i));
2105
2106 if (secfile_lookup_int(file, &uc->min_speed, "%s.min_speed", sec_name)) {
2107 uc->min_speed *= SINGLE_MOVE;
2108 } else {
2109 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
2110 ok = FALSE;
2111 break;
2112 }
2113 if (!secfile_lookup_int(file, &uc->hp_loss_pct,
2114 "%s.hp_loss_pct", sec_name)) {
2115 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
2116 ok = FALSE;
2117 break;
2118 }
2119
2120 uc->non_native_def_pct = secfile_lookup_int_default(file, 100,
2121 "%s.non_native_def_pct",
2122 sec_name);
2123
2124 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
2125 const char *hut_str;
2126
2127 hut_str = secfile_lookup_str_default(file, "Normal",
2128 "%s.hut_behavior", sec_name);
2129 if (fc_strcasecmp(hut_str, "Normal") == 0) {
2130 uc->rscompat_cache_from_3_0.hut_behavior = HUT_NORMAL;
2131 } else if (fc_strcasecmp(hut_str, "Nothing") == 0) {
2132 uc->rscompat_cache_from_3_0.hut_behavior = HUT_NOTHING;
2133 } else if (fc_strcasecmp(hut_str, "Frighten") == 0) {
2134 uc->rscompat_cache_from_3_0.hut_behavior = HUT_FRIGHTEN;
2135 } else {
2137 "\"%s\" unit_class \"%s\":"
2138 " Illegal hut behavior \"%s\".",
2139 filename, uclass_rule_name(uc), hut_str);
2140 ok = FALSE;
2141 break;
2142 }
2143 }
2144
2145 BV_CLR_ALL(uc->flags);
2147 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
2148 for (j = 0; j < nval; j++) {
2149 sval = slist[j];
2150 if (strcmp(sval, "") == 0) {
2151 continue;
2152 }
2153 ival = unit_class_flag_id_by_name(sval, fc_strcasecmp);
2154 if (!unit_class_flag_id_is_valid(ival)) {
2155 ok = FALSE;
2156 ival = unit_type_flag_id_by_name(rscompat_utype_flag_name_3_1(compat, sval),
2158 if (unit_type_flag_id_is_valid(ival)) {
2160 "\"%s\" unit_class \"%s\": unit_type flag \"%s\"!",
2161 filename, uclass_rule_name(uc), sval);
2162 } else {
2164 "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
2165 filename, uclass_rule_name(uc), sval);
2166 }
2167 break;
2168 } else {
2169 BV_SET(uc->flags, ival);
2170 }
2171 }
2172 free(slist);
2173
2174 uc->helptext = lookup_strvec(file, sec_name, "helptext");
2175
2176 if (!ok) {
2177 break;
2178 }
2180 }
2181
2182 if (ok) {
2183 /* Tech and Gov requirements; per unit veteran system */
2185 const int i = utype_index(u);
2186 const struct section *psection = section_list_get(sec, i);
2187 const char *sec_name = section_name(psection);
2188
2189 if (!lookup_tech(file, &u->require_advance, sec_name,
2190 "tech_req", filename,
2191 rule_name_get(&u->name))) {
2192 ok = FALSE;
2193 break;
2194 }
2195 if (u->require_advance == A_NEVER) {
2197 "%s lacks valid tech_req.",
2198 rule_name_get(&u->name));
2199 ok = FALSE;
2200 break;
2201 }
2202
2203 /* Read the government build requirement from the old ruleset format
2204 * and put it in unit_type's build_reqs requirement vector.
2205 * The build_reqs requirement vector isn't ready to be exposed in the
2206 * ruleset yet.
2207 * Barbarians can build certain units as long as anyone in the world
2208 * has the required tech. Regular players must have the required tech
2209 * them self to build the same unit. One way to solve this is to make
2210 * unit building an action enabler controlled action with a city (not
2211 * unit) actor.
2212 * Putting a requirement vector on unit types in the ruleset will
2213 * force ruleset authors to change all their unit type build
2214 * requirements to a requirement vector. Forcing them to convert their
2215 * unit type requirements again in the next version (should building be
2216 * switched to an action enabler with a city actor) is not good. */
2217 if (NULL != section_entry_by_name(psection, "gov_req")) {
2218 char tmp[200] = "\0";
2219 struct government *need_government;
2220
2221 fc_strlcat(tmp, section_name(psection), sizeof(tmp));
2222 fc_strlcat(tmp, ".gov_req", sizeof(tmp));
2223 need_government = lookup_government(file, tmp, filename, NULL);
2224 if (need_government == NULL) {
2225 ok = FALSE;
2226 break;
2227 }
2228 requirement_vector_append(&u->build_reqs, req_from_values(
2229 VUT_GOVERNMENT, REQ_RANGE_PLAYER,
2230 FALSE, TRUE, FALSE,
2231 government_number(need_government)));
2232 }
2233
2234 if (!load_ruleset_veteran(file, sec_name, &u->veteran,
2235 msg, sizeof(msg), compat)) {
2237 "Error loading the veteran system: %s",
2238 msg);
2239 ok = FALSE;
2240 break;
2241 }
2242
2243 if (!lookup_unit_type(file, sec_name, "obsolete_by",
2244 &u->obsoleted_by, filename,
2245 rule_name_get(&u->name))
2246 || !lookup_unit_type(file, sec_name, "convert_to",
2247 &u->converted_to, filename,
2248 rule_name_get(&u->name))) {
2249 ok = FALSE;
2250 break;
2251 }
2252 u->convert_time = 1; /* default */
2253 lookup_time(file, &u->convert_time, sec_name, "convert_time",
2254 filename, rule_name_get(&u->name), &ok);
2256 }
2257
2258 if (ok) {
2259 /* main stats: */
2261 const int i = utype_index(u);
2262 struct unit_class *pclass;
2263 const char *sec_name = section_name(section_list_get(sec, i));
2264 const char *str;
2265 struct impr_type *impr_req = NULL;
2266
2267 /* Read the building build requirement from the old ruleset format
2268 * and put it in unit_type's build_reqs requirement vector.
2269 * The build_reqs requirement vector isn't ready to be exposed in the
2270 * ruleset yet.
2271 * See the comment for gov_req above for why. */
2272 if (!lookup_building(file, sec_name, "impr_req",
2273 &impr_req, filename,
2274 rule_name_get(&u->name))) {
2275 ok = FALSE;
2276 break;
2277 }
2278 if (impr_req) {
2279 requirement_vector_append(&u->build_reqs, req_from_values(
2280 VUT_IMPROVEMENT, REQ_RANGE_CITY,
2281 FALSE, TRUE, FALSE,
2282 improvement_number(impr_req)));
2283 }
2284
2285 sval = secfile_lookup_str(file, "%s.class", sec_name);
2286 pclass = unit_class_by_rule_name(sval);
2287 if (!pclass) {
2289 "\"%s\" unit_type \"%s\": bad class \"%s\".",
2290 filename, utype_rule_name(u), sval);
2291 ok = FALSE;
2292 break;
2293 }
2294 u->uclass = pclass;
2295
2296 sz_strlcpy(u->sound_move,
2297 secfile_lookup_str_default(file, "-", "%s.sound_move",
2298 sec_name));
2299 sz_strlcpy(u->sound_move_alt,
2300 secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
2301 sec_name));
2302 sz_strlcpy(u->sound_fight,
2303 secfile_lookup_str_default(file, "-", "%s.sound_fight",
2304 sec_name));
2305 sz_strlcpy(u->sound_fight_alt,
2306 secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
2307 sec_name));
2308
2309 if ((str = secfile_lookup_str(file, "%s.graphic", sec_name))) {
2310 sz_strlcpy(u->graphic_str, str);
2311 } else {
2312 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
2313 ok = FALSE;
2314 break;
2315 }
2316 sz_strlcpy(u->graphic_alt,
2317 secfile_lookup_str_default(file, "-", "%s.graphic_alt",
2318 sec_name));
2319
2320 if (!secfile_lookup_int(file, &u->build_cost,
2321 "%s.build_cost", sec_name)
2322 || !secfile_lookup_int(file, &u->pop_cost,
2323 "%s.pop_cost", sec_name)
2324 || !secfile_lookup_int(file, &u->attack_strength,
2325 "%s.attack", sec_name)
2326 || !secfile_lookup_int(file, &u->defense_strength,
2327 "%s.defense", sec_name)
2328 || !secfile_lookup_int(file, &u->move_rate,
2329 "%s.move_rate", sec_name)
2330 || !secfile_lookup_int(file, &u->vision_radius_sq,
2331 "%s.vision_radius_sq", sec_name)
2332 || !secfile_lookup_int(file, &u->transport_capacity,
2333 "%s.transport_cap", sec_name)
2334 || !secfile_lookup_int(file, &u->hp,
2335 "%s.hitpoints", sec_name)
2336 || !secfile_lookup_int(file, &u->firepower,
2337 "%s.firepower", sec_name)
2338 || !secfile_lookup_int(file, &u->fuel,
2339 "%s.fuel", sec_name)
2340 || !secfile_lookup_int(file, &u->happy_cost,
2341 "%s.uk_happy", sec_name)) {
2342 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
2343 ok = FALSE;
2344 break;
2345 }
2346 u->move_rate *= SINGLE_MOVE;
2347
2348 if (u->firepower <= 0) {
2350 "\"%s\" unit_type \"%s\":"
2351 " firepower is %d,"
2352 " but must be at least 1. "
2353 " If you want no attack ability,"
2354 " set the unit's attack strength to 0.",
2355 filename, utype_rule_name(u), u->firepower);
2356 ok = FALSE;
2357 break;
2358 }
2359
2360 lookup_cbonus_list(compat, u->bonuses, file, sec_name, "bonuses");
2361
2363 u->upkeep[o] = secfile_lookup_int_default(file, 0, "%s.uk_%s",
2364 sec_name,
2367
2368 slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec_name);
2369 if (u->transport_capacity > 0) {
2370 if (nval == 0) {
2372 "\"%s\" unit type \"%s\" "
2373 "has transport_cap %d, but no cargo unit classes.",
2374 filename, utype_rule_name(u), u->transport_capacity);
2375 ok = FALSE;
2376 break;
2377 }
2378 } else {
2379 if (nval > 0) {
2381 "\"%s\" unit type \"%s\" "
2382 "has cargo defined, but transport_cap is 0.",
2383 filename, utype_rule_name(u));
2384 ok = FALSE;
2385 break;
2386 }
2387 }
2388
2389 BV_CLR_ALL(u->cargo);
2390 for (j = 0; j < nval; j++) {
2391 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2392
2393 if (!uclass) {
2395 "\"%s\" unit_type \"%s\":"
2396 "has unknown unit class %s as cargo.",
2397 filename, utype_rule_name(u), slist[j]);
2398 ok = FALSE;
2399 break;
2400 }
2401
2402 BV_SET(u->cargo, uclass_index(uclass));
2403 }
2404 free(slist);
2405
2406 if (!ok) {
2407 break;
2408 }
2409
2410 slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec_name);
2411 BV_CLR_ALL(u->targets);
2412 for (j = 0; j < nval; j++) {
2413 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2414
2415 if (!uclass) {
2417 "\"%s\" unit_type \"%s\":"
2418 "has unknown unit class %s as target.",
2419 filename, utype_rule_name(u), slist[j]);
2420 ok = FALSE;
2421 break;
2422 }
2423
2424 BV_SET(u->targets, uclass_index(uclass));
2425 }
2426 free(slist);
2427
2428 if (!ok) {
2429 break;
2430 }
2431
2432 slist = secfile_lookup_str_vec(file, &nval, "%s.embarks", sec_name);
2433 BV_CLR_ALL(u->embarks);
2434 for (j = 0; j < nval; j++) {
2435 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2436
2437 if (!uclass) {
2439 "\"%s\" unit_type \"%s\":"
2440 "has unknown unit class %s as embarkable.",
2441 filename, utype_rule_name(u), slist[j]);
2442 ok = FALSE;
2443 break;
2444 }
2445
2446 BV_SET(u->embarks, uclass_index(uclass));
2447 }
2448 free(slist);
2449
2450 if (!ok) {
2451 break;
2452 }
2453
2454 slist = secfile_lookup_str_vec(file, &nval, "%s.disembarks", sec_name);
2455 BV_CLR_ALL(u->disembarks);
2456 for (j = 0; j < nval; j++) {
2457 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2458
2459 if (!uclass) {
2461 "\"%s\" unit_type \"%s\":"
2462 "has unknown unit class %s as disembarkable.",
2463 filename, utype_rule_name(u), slist[j]);
2464 ok = FALSE;
2465 break;
2466 }
2467
2468 BV_SET(u->disembarks, uclass_index(uclass));
2469 }
2470 free(slist);
2471
2472 if (!ok) {
2473 break;
2474 }
2475
2476 /* Set also all classes that are never unreachable as targets,
2477 * embarks, and disembarks. */
2478 unit_class_iterate(preachable) {
2479 if (!uclass_has_flag(preachable, UCF_UNREACHABLE)) {
2480 BV_SET(u->targets, uclass_index(preachable));
2481 BV_SET(u->embarks, uclass_index(preachable));
2482 BV_SET(u->disembarks, uclass_index(preachable));
2483 }
2485
2486 str = secfile_lookup_str_default(file, "Main", "%s.vision_layer",
2487 sec_name);
2488 u->vlayer = vision_layer_by_name(str, fc_strcasecmp);
2489 if (!vision_layer_is_valid(u->vlayer)) {
2491 "\"%s\" unit_type \"%s\":"
2492 "has unknown vision layer %s.",
2493 filename, utype_rule_name(u), str);
2494 ok = FALSE;
2495 break;
2496 }
2497
2498 u->helptext = lookup_strvec(file, sec_name, "helptext");
2499
2500 u->paratroopers_range = secfile_lookup_int_default(file,
2501 0, "%s.paratroopers_range", sec_name);
2502 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
2503 u->rscompat_cache.paratroopers_mr_req
2505 file, 0, "%s.paratroopers_mr_req", sec_name);
2506 u->rscompat_cache.paratroopers_mr_sub
2508 file, 0, "%s.paratroopers_mr_sub", sec_name);
2509 } else {
2510 u->rscompat_cache.paratroopers_mr_req = 0;
2511 u->rscompat_cache.paratroopers_mr_sub = 0;
2512 }
2513 u->bombard_rate = secfile_lookup_int_default(file, 0,
2514 "%s.bombard_rate", sec_name);
2515 u->city_slots = secfile_lookup_int_default(file, 0,
2516 "%s.city_slots", sec_name);
2517 u->city_size = secfile_lookup_int_default(file, 1,
2518 "%s.city_size", sec_name);
2519
2520 sval = secfile_lookup_str_default(file, transp_def_type_name(TDT_ALIGHT),
2521 "%s.tp_defense", sec_name);
2522 u->tp_defense = transp_def_type_by_name(sval, fc_strcasecmp);
2523 if (!transp_def_type_is_valid(u->tp_defense)) {
2525 "\"%s\" unit_type \"%s\":"
2526 " bad tp_defense \"%s\".",
2527 filename, utype_rule_name(u), sval);
2528 ok = FALSE;
2529 break;
2530 }
2532 }
2533
2534 if (ok) {
2535 /* flags */
2537 const int i = utype_index(u);
2538
2539 BV_CLR_ALL(u->flags);
2541
2542 slist = secfile_lookup_str_vec(file, &nval, "%s.flags",
2543 section_name(section_list_get(sec, i)));
2544 for (j = 0; j < nval; j++) {
2545 sval = slist[j];
2546 if (0 == strcmp(sval, "")) {
2547 continue;
2548 }
2549 if (compat->compat_mode && !fc_strcasecmp("Partial_Invis", sval)) {
2550 u->vlayer = V_INVIS;
2551 } else {
2552 ival = unit_type_flag_id_by_name(rscompat_utype_flag_name_3_1(compat, sval),
2554 if (!unit_type_flag_id_is_valid(ival)) {
2555 ok = FALSE;
2556 ival = unit_class_flag_id_by_name(sval, fc_strcasecmp);
2557 if (unit_class_flag_id_is_valid(ival)) {
2559 "\"%s\" unit_type \"%s\": unit_class flag!",
2560 filename, utype_rule_name(u));
2561 } else {
2563 "\"%s\" unit_type \"%s\": bad flag name \"%s\".",
2564 filename, utype_rule_name(u), sval);
2565 }
2566 break;
2567 } else {
2568 BV_SET(u->flags, ival);
2569 }
2570 fc_assert(utype_has_flag(u, ival));
2571 }
2572 }
2573 free(slist);
2574
2575 if (!ok) {
2576 break;
2577 }
2579 }
2580
2581 /* roles */
2582 if (ok) {
2584 const int i = utype_index(u);
2585
2586 BV_CLR_ALL(u->roles);
2587
2588 slist = secfile_lookup_str_vec(file, &nval, "%s.roles",
2589 section_name(section_list_get(sec, i)));
2590 for (j = 0; j < nval; j++) {
2591 sval = slist[j];
2592 if (strcmp(sval, "") == 0) {
2593 continue;
2594 }
2595 ival = unit_role_id_by_name(sval, fc_strcasecmp);
2596 if (!unit_role_id_is_valid(ival)) {
2598 "\"%s\" unit_type \"%s\": bad role name \"%s\".",
2599 filename, utype_rule_name(u), sval);
2600 ok = FALSE;
2601 break;
2602 } else {
2603 BV_SET(u->roles, ival - L_FIRST);
2604 }
2605 fc_assert(utype_has_role(u, ival));
2606 }
2607 free(slist);
2609 }
2610
2611 if (ok) {
2612 /* Some more consistency checking: */
2614 if (!valid_advance(u->require_advance)) {
2616 "\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
2617 filename, utype_rule_name(u),
2618 advance_rule_name(u->require_advance));
2619 u->require_advance = A_NEVER;
2620 ok = FALSE;
2621 break;
2622 }
2624 }
2625
2626 section_list_destroy(csec);
2627 section_list_destroy(sec);
2628
2629 if (ok) {
2631 }
2632
2633 return ok;
2634}
2635
2636/**********************************************************************/
2640static bool load_building_names(struct section_file *file,
2641 struct rscompat_info *compat)
2642{
2643 struct section_list *sec;
2644 int i, nval = 0;
2645 const char *filename = secfile_name(file);
2646 bool ok = TRUE;
2647
2648 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2649 return FALSE;
2650 }
2651
2652 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2653 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2654
2655 /* The names: */
2657 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2659 "\"%s\": No improvements?!?", filename);
2660 ok = FALSE;
2661 } else {
2662 log_verbose("%d improvement types (including possibly unused)", nval);
2663 if (nval > B_LAST) {
2665 "\"%s\": Too many improvements (%d, max %d)",
2666 filename, nval, B_LAST);
2667 ok = FALSE;
2668 }
2669 }
2670
2671 if (ok) {
2673
2674 for (i = 0; i < nval; i++) {
2675 struct impr_type *b = improvement_by_number(i);
2676
2677 if (!ruleset_load_names(&b->name, NULL, file, section_name(section_list_get(sec, i)))) {
2678 ok = FALSE;
2679 break;
2680 }
2681 }
2682 }
2683
2684 section_list_destroy(sec);
2685
2686 return ok;
2687}
2688
2689/**********************************************************************/
2692static bool load_ruleset_buildings(struct section_file *file,
2693 struct rscompat_info *compat)
2694{
2695 struct section_list *sec;
2696 const char *item;
2697 int i, nval;
2698 const char *filename = secfile_name(file);
2699 bool ok = TRUE;
2700
2702 nval = (NULL != sec ? section_list_size(sec) : 0);
2703
2704 for (i = 0; i < nval && ok; i++) {
2705 struct impr_type *b = improvement_by_number(i);
2706 const char *sec_name = section_name(section_list_get(sec, i));
2707 struct requirement_vector *reqs =
2708 lookup_req_list(file, compat, sec_name, "reqs",
2710
2711 if (reqs == NULL) {
2712 ok = FALSE;
2713 break;
2714 } else {
2715 const char *sval, **slist;
2716 int j, ival;
2717 size_t nflags;
2718
2719 item = secfile_lookup_str(file, "%s.genus", sec_name);
2720 b->genus = impr_genus_id_by_name(item, fc_strcasecmp);
2721 if (!impr_genus_id_is_valid(b->genus)) {
2723 "\"%s\" improvement \"%s\": couldn't match "
2724 "genus \"%s\".", filename,
2726 ok = FALSE;
2727 break;
2728 }
2729
2730 slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec_name);
2731 BV_CLR_ALL(b->flags);
2732
2733 for (j = 0; j < nflags; j++) {
2734 sval = slist[j];
2735 if (strcmp(sval, "") == 0) {
2736 continue;
2737 }
2738 ival = impr_flag_id_by_name(sval, fc_strcasecmp);
2739 if (!impr_flag_id_is_valid(ival)) {
2741 "\"%s\" improvement \"%s\": bad flag name \"%s\".",
2742 filename, improvement_rule_name(b), sval);
2743 ok = FALSE;
2744 break;
2745 } else {
2746 BV_SET(b->flags, ival);
2747 }
2748 }
2749 free(slist);
2750
2751 if (!ok) {
2752 break;
2753 }
2754
2755 requirement_vector_copy(&b->reqs, reqs);
2756
2757 {
2758 struct requirement_vector *obs_reqs =
2759 lookup_req_list(file, compat, sec_name, "obsolete_by",
2761
2762 if (obs_reqs == NULL) {
2763 ok = FALSE;
2764 break;
2765 } else {
2766 requirement_vector_copy(&b->obsolete_by, obs_reqs);
2767 }
2768 }
2769
2770 if (!secfile_lookup_int(file, &b->build_cost,
2771 "%s.build_cost", sec_name)
2772 || !secfile_lookup_int(file, &b->upkeep,
2773 "%s.upkeep", sec_name)
2774 || !secfile_lookup_int(file, &b->sabotage,
2775 "%s.sabotage", sec_name)) {
2776 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
2777 ok = FALSE;
2778 break;
2779 }
2780
2783 "%s.graphic", sec_name));
2786 "%s.graphic_alt", sec_name));
2787
2790 "%s.sound", sec_name));
2793 "%s.sound_alt", sec_name));
2794 b->helptext = lookup_strvec(file, sec_name, "helptext");
2795 }
2796 }
2797
2798 section_list_destroy(sec);
2799 if (ok) {
2801 }
2802
2803 return ok;
2804}
2805
2806/**********************************************************************/
2810static bool load_terrain_names(struct section_file *file,
2811 struct rscompat_info *compat)
2812{
2813 int nval = 0;
2814 struct section_list *sec = NULL;
2815 const char *flag;
2816 int i;
2817 const char *filename = secfile_name(file);
2818 bool ok = TRUE;
2819
2820 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2821 return FALSE;
2822 }
2823
2824 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2825 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2826
2827 /* User terrain flag names */
2828 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
2829 i++) {
2830 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
2831 i);
2832
2833 if (terrain_flag_id_by_name(flag, fc_strcasecmp)
2834 != terrain_flag_id_invalid()) {
2836 "\"%s\": Duplicate terrain flag name '%s'",
2837 filename, flag);
2838 ok = FALSE;
2839 break;
2840 }
2841 if (i > MAX_NUM_USER_TER_FLAGS) {
2843 "\"%s\": Too many user terrain flags!",
2844 filename);
2845 ok = FALSE;
2846 break;
2847 }
2848
2849 set_user_terrain_flag_name(TER_USER_1 + i, flag, helptxt);
2850 }
2851
2852 if (ok) {
2853 /* Blank the remaining terrain user flag slots. */
2854 for (; i < MAX_NUM_USER_TER_FLAGS; i++) {
2855 set_user_terrain_flag_name(TER_USER_1 + i, NULL, NULL);
2856 }
2857 }
2858
2859 /* User extra flag names */
2860 for (i = 0;
2861 (flag = secfile_lookup_str_default(file, NULL,
2862 "control.extra_flags%d.name",
2863 i));
2864 i++) {
2865 const char *helptxt = secfile_lookup_str_default(file, NULL,
2866 "control.extra_flags%d.helptxt", i);
2867
2868 if (extra_flag_id_by_name(flag, fc_strcasecmp)
2869 != extra_flag_id_invalid()) {
2871 "\"%s\": Duplicate extra flag name '%s'",
2872 filename, flag);
2873 ok = FALSE;
2874 break;
2875 }
2876 if (i > MAX_NUM_USER_EXTRA_FLAGS) {
2878 "\"%s\": Too many user extra flags!",
2879 filename);
2880 ok = FALSE;
2881 break;
2882 }
2883
2884 set_user_extra_flag_name(EF_USER_FLAG_1 + i, flag, helptxt);
2885 }
2886
2887 if (ok) {
2888 /* Blank the remaining extra user flag slots. */
2889 for (; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
2890 set_user_extra_flag_name(EF_USER_FLAG_1 + i, NULL, NULL);
2891 }
2892
2893 /* terrain names */
2894
2896 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2898 "\"%s\": ruleset doesn't have any terrains.",
2899 filename);
2900 ok = FALSE;
2901 } else {
2902 if (nval > MAX_NUM_TERRAINS) {
2904 "\"%s\": Too many terrains (%d, max %d)",
2905 filename, nval, MAX_NUM_TERRAINS);
2906 ok = FALSE;
2907 }
2908 }
2909 }
2910
2911 if (ok) {
2912 game.control.terrain_count = nval;
2913
2914 /* avoid re-reading files */
2915 if (terrain_sections) {
2916 free(terrain_sections);
2917 }
2919
2920 terrain_type_iterate(pterrain) {
2921 const int terri = terrain_index(pterrain);
2922 const char *sec_name = section_name(section_list_get(sec, terri));
2923
2924 if (!ruleset_load_names(&pterrain->name, NULL, file, sec_name)) {
2925 ok = FALSE;
2926 break;
2927 }
2928
2931 }
2932
2933 section_list_destroy(sec);
2934 sec = NULL;
2935
2936 /* extra names */
2937
2938 if (ok) {
2940 nval = (NULL != sec ? section_list_size(sec) : 0);
2941 if (nval > MAX_EXTRA_TYPES) {
2943 "\"%s\": Too many extra types (%d, max %d)",
2944 filename, nval, MAX_EXTRA_TYPES);
2945 ok = FALSE;
2946 }
2947 }
2948
2949 if (ok) {
2950 int idx;
2951
2953
2954 if (extra_sections) {
2955 free(extra_sections);
2956 }
2958
2959 if (ok) {
2960 for (idx = 0; idx < nval; idx++) {
2961 const char *sec_name = section_name(section_list_get(sec, idx));
2962 struct extra_type *pextra = extra_by_number(idx);
2963
2964 if (!ruleset_load_names(&pextra->name, NULL, file, sec_name)) {
2965 ok = FALSE;
2966 break;
2967 }
2969 }
2970 }
2971 }
2972
2973 section_list_destroy(sec);
2974 sec = NULL;
2975
2976 /* Base names */
2977
2978 if (ok) {
2980 nval = (NULL != sec ? section_list_size(sec) : 0);
2981 if (nval > MAX_EXTRA_TYPES) {
2983 "\"%s\": Too many base types (%d, max %d)",
2984 filename, nval, MAX_EXTRA_TYPES);
2985 ok = FALSE;
2986 }
2987
2989 }
2990
2991 if (ok) {
2992 int idx;
2993
2994 if (base_sections) {
2995 free(base_sections);
2996 }
2998
2999 /* Cannot use base_type_iterate() before bases are added to
3000 * EC_BASE caused_by list. Have to get them by extra_type_by_rule_name() */
3001 for (idx = 0; idx < nval; idx++) {
3002 const char *sec_name = section_name(section_list_get(sec, idx));
3003 const char *base_name = secfile_lookup_str(file, "%s.extra", sec_name);
3004
3005 if (base_name != NULL) {
3006 struct extra_type *pextra = extra_type_by_rule_name(base_name);
3007
3008 if (pextra != NULL) {
3009 base_type_init(pextra, idx);
3011 } else {
3013 "No extra definition matching base definition \"%s\"",
3014 base_name);
3015 ok = FALSE;
3016 }
3017 } else {
3019 "Base section \"%s\" does not associate base with any extra",
3020 sec_name);
3021 ok = FALSE;
3022 }
3023 }
3024 }
3025
3026 section_list_destroy(sec);
3027 sec = NULL;
3028
3029 /* Road names */
3030
3031 if (ok) {
3033 nval = (NULL != sec ? section_list_size(sec) : 0);
3034 if (nval > MAX_EXTRA_TYPES) {
3036 "\"%s\": Too many road types (%d, max %d)",
3037 filename, nval, MAX_EXTRA_TYPES);
3038 ok = FALSE;
3039 }
3040
3042 }
3043
3044 if (ok) {
3045 int idx;
3046
3047 if (road_sections) {
3048 free(road_sections);
3049 }
3051
3052 /* Cannot use extra_type_by_cause_iterate(EC_ROAD) before roads are added to
3053 * EC_ROAD caused_by list. Have to get them by extra_type_by_rule_name() */
3054 for (idx = 0; idx < nval; idx++) {
3055 const char *sec_name = section_name(section_list_get(sec, idx));
3056 const char *road_name = secfile_lookup_str(file, "%s.extra", sec_name);
3057
3058 if (road_name != NULL) {
3059 struct extra_type *pextra = extra_type_by_rule_name(road_name);
3060
3061 if (pextra != NULL) {
3062 road_type_init(pextra, idx);
3064 } else {
3066 "No extra definition matching road definition \"%s\"",
3067 road_name);
3068 ok = FALSE;
3069 }
3070 } else {
3072 "Road section \"%s\" does not associate road with any extra",
3073 sec_name);
3074 ok = FALSE;
3075 }
3076 }
3077 }
3078
3079 section_list_destroy(sec);
3080 sec = NULL;
3081
3082 /* resource names */
3083
3084 if (ok) {
3086 nval = (NULL != sec ? section_list_size(sec) : 0);
3087 if (nval > MAX_RESOURCE_TYPES) {
3089 "\"%s\": Too many resource types (%d, max %d)",
3090 filename, nval, MAX_RESOURCE_TYPES);
3091 ok = FALSE;
3092 }
3093
3095 }
3096
3097 if (ok) {
3098 int idx;
3099
3100 if (resource_sections) {
3101 free(resource_sections);
3102 }
3104
3105 /* Cannot use resource_type_iterate() before resource are added to
3106 * EC_RESOURCE caused_by list. Have to get them by extra_type_by_rule_name() */
3107 for (idx = 0; idx < nval; idx++) {
3108 const char *sec_name = section_name(section_list_get(sec, idx));
3109 const char *resource_name;
3110 struct extra_type *pextra = NULL;
3111
3112 resource_name = secfile_lookup_str_default(file, NULL, "%s.extra", sec_name);
3113
3114 if (resource_name != NULL) {
3115 pextra = extra_type_by_rule_name(resource_name);
3116
3117 if (pextra != NULL) {
3118 resource_type_init(pextra);
3120 } else {
3122 "No extra definition matching resource definition \"%s\"",
3123 resource_name);
3124 ok = FALSE;
3125 }
3126 } else {
3128 "Resource section %s does not list extra this resource belongs to.",
3129 sec_name);
3130 ok = FALSE;
3131 }
3132 }
3133 }
3134
3135 section_list_destroy(sec);
3136
3137 return ok;
3138}
3139
3140/**********************************************************************/
3143static bool load_ruleset_terrain(struct section_file *file,
3144 struct rscompat_info *compat)
3145{
3146 size_t nval;
3147 int j;
3148 bool compat_road = FALSE;
3149 bool compat_rail = FALSE;
3150 bool compat_river = FALSE;
3151 const char **res;
3152 const char *filename = secfile_name(file);
3153 const char *text;
3154 bool ok = TRUE;
3155
3156 /* parameters */
3157
3158 terrain_control.ocean_reclaim_requirement_pct
3159 = secfile_lookup_int_default(file, 101,
3160 "parameters.ocean_reclaim_requirement");
3161 terrain_control.land_channel_requirement_pct
3162 = secfile_lookup_int_default(file, 101,
3163 "parameters.land_channel_requirement");
3164 terrain_control.terrain_thaw_requirement_pct
3165 = secfile_lookup_int_default(file, 101,
3166 "parameters.thaw_requirement");
3167 terrain_control.terrain_freeze_requirement_pct
3168 = secfile_lookup_int_default(file, 101,
3169 "parameters.freeze_requirement");
3170 terrain_control.lake_max_size
3172 "parameters.lake_max_size");
3173 terrain_control.min_start_native_area
3175 "parameters.min_start_native_area");
3176 terrain_control.move_fragments
3178 "parameters.move_fragments");
3179 if (terrain_control.move_fragments < 1) {
3181 "\"%s\": move_fragments must be at least 1",
3182 filename);
3183 ok = FALSE;
3184 }
3186 terrain_control.igter_cost
3188 "parameters.igter_cost");
3189 if (terrain_control.igter_cost < 1) {
3191 "\"%s\": igter_cost must be at least 1",
3192 filename);
3193 ok = FALSE;
3194 }
3195 terrain_control.infrapoints = FALSE; /* This will be updated if we find
3196 * an placeable extra. */
3197
3198 terrain_control.pythagorean_diagonal
3200 "parameters.pythagorean_diagonal");
3201
3204 "parameters.ocean_resources");
3205
3206 text = secfile_lookup_str_default(file,
3207 N_("?gui_type:Build Type A Base"),
3208 "extraui.ui_name_base_fortress");
3209 sz_strlcpy(terrain_control.gui_type_base0, text);
3210
3211 text = secfile_lookup_str_default(file,
3212 N_("?gui_type:Build Type B Base"),
3213 "extraui.ui_name_base_airbase");
3214 sz_strlcpy(terrain_control.gui_type_base1, text);
3215
3216 if (ok) {
3217 /* terrain details */
3218
3219 terrain_type_iterate(pterrain) {
3220 const char **slist;
3221 const int i = terrain_index(pterrain);
3222 const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
3223 const char *cstr;
3224
3225 sz_strlcpy(pterrain->graphic_str,
3226 secfile_lookup_str(file, "%s.graphic", tsection));
3227 sz_strlcpy(pterrain->graphic_alt,
3228 secfile_lookup_str(file, "%s.graphic_alt", tsection));
3229
3230 pterrain->identifier
3231 = secfile_lookup_str(file, "%s.identifier", tsection)[0];
3232 if ('\0' == pterrain->identifier) {
3234 "\"%s\" [%s] identifier missing value.",
3235 filename, tsection);
3236 ok = FALSE;
3237 break;
3238 }
3239 if (TERRAIN_UNKNOWN_IDENTIFIER == pterrain->identifier) {
3241 "\"%s\" [%s] cannot use '%c' as an identifier;"
3242 " it is reserved for unknown terrain.",
3243 filename, tsection, pterrain->identifier);
3244 ok = FALSE;
3245 break;
3246 }
3247 for (j = T_FIRST; j < i; j++) {
3248 if (pterrain->identifier == terrain_by_number(j)->identifier) {
3250 "\"%s\" [%s] has the same identifier as [%s].",
3251 filename, tsection,
3253 ok = FALSE;
3254 break;
3255 }
3256 }
3257
3258 if (!ok) {
3259 break;
3260 }
3261
3262 cstr = secfile_lookup_str(file, "%s.class", tsection);
3263 pterrain->tclass = terrain_class_by_name(cstr, fc_strcasecmp);
3264 if (!terrain_class_is_valid(pterrain->tclass)) {
3266 "\"%s\": [%s] unknown class \"%s\"",
3267 filename, tsection, cstr);
3268 ok = FALSE;
3269 break;
3270 }
3271
3272 if (!secfile_lookup_int(file, &pterrain->movement_cost,
3273 "%s.movement_cost", tsection)
3274 || !secfile_lookup_int(file, &pterrain->defense_bonus,
3275 "%s.defense_bonus", tsection)) {
3276 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
3277 ok = FALSE;
3278 break;
3279 }
3280
3282 pterrain->output[o]
3283 = secfile_lookup_int_default(file, 0, "%s.%s", tsection,
3286
3287 res = secfile_lookup_str_vec(file, &nval, "%s.resources", tsection);
3288 pterrain->resources = fc_calloc(nval + 1, sizeof(*pterrain->resources));
3289 for (j = 0; j < nval; j++) {
3290 pterrain->resources[j] = lookup_resource(filename, res[j], tsection);
3291 if (pterrain->resources[j] == NULL) {
3292 ok = FALSE;
3293 break;
3294 }
3295 }
3296 pterrain->resources[nval] = NULL;
3297 free(res);
3298 res = NULL;
3299
3300 if (!ok) {
3301 break;
3302 }
3303
3305 pterrain->road_output_incr_pct[o]
3306 = secfile_lookup_int_default(file, 0, "%s.road_%s_incr_pct",
3307 tsection, get_output_identifier(o));
3309
3310 if (!lookup_time(file, &pterrain->base_time, tsection, "base_time",
3311 filename, NULL, &ok)
3312 || !lookup_time(file, &pterrain->road_time, tsection, "road_time",
3313 filename, NULL, &ok)) {
3314 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
3315 ok = FALSE;
3316 break;
3317 }
3318
3319 if (!lookup_terrain(file, "cultivate_result", filename, pterrain,
3320 &pterrain->cultivate_result, FALSE)) {
3321 if (compat->compat_mode) {
3322 if (!lookup_terrain(file, "irrigation_result", filename, pterrain,
3323 &pterrain->cultivate_result, TRUE)) {
3324 ok = FALSE;
3325 break;
3326 }
3327 } else {
3328 ruleset_error(NULL, LOG_ERROR, "%s: No cultivate_result", tsection);
3329 ok = FALSE;
3330 break;
3331 }
3332 }
3333 if (!compat->compat_mode && pterrain->cultivate_result == pterrain) {
3335 "%s: Cultivating result in terrain itself.",
3336 tsection);
3337 ok = FALSE;
3338 break;
3339 }
3340 if (!secfile_lookup_int(file, &pterrain->irrigation_food_incr,
3341 "%s.irrigation_food_incr", tsection)
3342 || !lookup_time(file, &pterrain->irrigation_time,
3343 tsection, "irrigation_time", filename, NULL, &ok)) {
3344 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
3345 ok = FALSE;
3346 break;
3347 }
3348
3349 if (!lookup_terrain(file, "plant_result", filename, pterrain,
3350 &pterrain->plant_result, FALSE)) {
3351 if (compat->compat_mode) {
3352 if (!lookup_terrain(file, "mining_result", filename, pterrain,
3353 &pterrain->plant_result, TRUE)) {
3354 ok = FALSE;
3355 break;
3356 }
3357 } else {
3358 ruleset_error(NULL, LOG_ERROR, "%s: No plant_result", tsection);
3359 ok = FALSE;
3360 break;
3361 }
3362 }
3363 if (!compat->compat_mode && pterrain->plant_result == pterrain) {
3365 "%s: Planting result in terrain itself.",
3366 tsection);
3367 ok = FALSE;
3368 break;
3369 }
3370 if (!secfile_lookup_int(file, &pterrain->mining_shield_incr,
3371 "%s.mining_shield_incr", tsection)
3372 || !lookup_time(file, &pterrain->mining_time,
3373 tsection, "mining_time", filename, NULL, &ok)) {
3374 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
3375 ok = FALSE;
3376 break;
3377 }
3378
3379 if (!lookup_time(file, &pterrain->cultivate_time,
3380 tsection, "cultivate_time", filename, NULL, &ok)) {
3381 if (compat->compat_mode) {
3382 if (pterrain->cultivate_result != pterrain) {
3383 if (pterrain->cultivate_result == NULL && pterrain->irrigation_time != 0) {
3384 /* Make sure cultivate_time is zero when cultivate_result is "no".
3385 * In S3_0 it was legal to have any kind of _time value when _result was "no",
3386 * it was just ignored. We no longer accept that. */
3387 if (compat->log_cb != NULL) {
3388 char buf[512];
3389
3390 fc_snprintf(buf, sizeof(buf),
3391 "Changed %s cultivate_time to zero, as it inconsistently had "
3392 "irrigation_result \"no\" and nonzero irrigation_time.",
3393 tsection);
3394 compat->log_cb(buf);
3395 }
3396 pterrain->cultivate_time = 0;
3397 } else {
3398 pterrain->cultivate_time = pterrain->irrigation_time;
3399 }
3400 pterrain->irrigation_time = 0;
3401 } else {
3402 pterrain->cultivate_time = 0;
3403 pterrain->cultivate_result = NULL;
3404 }
3405 } else {
3407 "%s: Missing cultivate_time", tsection);
3408 ok = FALSE;
3409 break;
3410 }
3411 }
3412 if ((pterrain->cultivate_result != NULL
3413 && pterrain->cultivate_time <= 0)
3414 || (pterrain->cultivate_result == NULL
3415 && pterrain->cultivate_time > 0)) {
3417 "%s: cultivate_result and cultivate_time disagree "
3418 "whether cultivating is enabled", tsection);
3419 ok = FALSE;
3420 break;
3421 }
3422
3423 if (!lookup_time(file, &pterrain->plant_time,
3424 tsection, "plant_time", filename, NULL, &ok)) {
3425 if (compat->compat_mode) {
3426 if (pterrain->plant_result != pterrain) {
3427 if (pterrain->plant_result == NULL && pterrain->mining_time != 0) {
3428 /* Make sure plant_time is zero when plant_result is "no".
3429 * In S3_0 it was legal to have any kind of _time value when _result was "no",
3430 * it was just ignored. We no longer accept that. */
3431 if (compat->log_cb != NULL) {
3432 char buf[512];
3433
3434 fc_snprintf(buf, sizeof(buf),
3435 "Changed %s plant_time to zero, as it inconsistently had "
3436 "mining_result \"no\" and nonzero mining_time.",
3437 tsection);
3438 compat->log_cb(buf);
3439 }
3440 pterrain->plant_time = 0;
3441 } else {
3442 pterrain->plant_time = pterrain->mining_time;
3443 }
3444 pterrain->mining_time = 0;
3445 } else {
3446 pterrain->plant_time = 0;
3447 pterrain->plant_result = NULL;
3448 }
3449 } else {
3450 ruleset_error(NULL, LOG_ERROR, "%s: Missing plant_time", tsection);
3451 ok = FALSE;
3452 break;
3453 }
3454
3455 }
3456 if ((pterrain->plant_result != NULL
3457 && pterrain->plant_time <= 0)
3458 || (pterrain->plant_result == NULL
3459 && pterrain->plant_time > 0)) {
3461 "%s: plant_result and plant_time disagree "
3462 "whether planting is enabled", tsection);
3463 ok = FALSE;
3464 break;
3465 }
3466
3467 if (!lookup_unit_type(file, tsection, "animal",
3468 &pterrain->animal, filename,
3469 rule_name_get(&pterrain->name))) {
3470 ok = FALSE;
3471 break;
3472 }
3473
3474 if (!lookup_terrain(file, "transform_result", filename, pterrain,
3475 &pterrain->transform_result, TRUE)) {
3476 ok = FALSE;
3477 break;
3478 }
3479 if (!lookup_time(file, &pterrain->transform_time,
3480 tsection, "transform_time", filename, NULL, &ok)) {
3481 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
3482 ok = FALSE;
3483 break;
3484 }
3485 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
3486 if (pterrain->transform_time <= 0) {
3487 /* Transform time of zero was documented to disable the transform
3488 * regardless of given transform result in earlier versions, i.e.,
3489 * having them inconsistent was not an error. */
3490 pterrain->transform_result = NULL;
3491 } else if (pterrain->transform_result == NULL) {
3492 pterrain->transform_time = 0;
3493 }
3494 }
3495 if ((pterrain->transform_result != NULL
3496 && pterrain->transform_time <= 0)
3497 || (pterrain->transform_result == NULL
3498 && pterrain->transform_time > 0)) {
3500 "%s: transform_result and transform_time disagree "
3501 "whether transforming is enabled", tsection);
3502 ok = FALSE;
3503 break;
3504 }
3505
3506 pterrain->placing_time = 1; /* default */
3507 lookup_time(file, &pterrain->placing_time,
3508 tsection, "placing_time", filename, NULL, &ok);
3509
3510 pterrain->pillage_time = 1; /* default */
3511 lookup_time(file, &pterrain->pillage_time,
3512 tsection, "pillage_time", filename, NULL, &ok);
3513 pterrain->clean_pollution_time = 3; /* default */
3514 lookup_time(file, &pterrain->clean_pollution_time,
3515 tsection, "clean_pollution_time", filename, NULL, &ok);
3516 pterrain->clean_fallout_time = 3; /* default */
3517 lookup_time(file, &pterrain->clean_fallout_time,
3518 tsection, "clean_fallout_time", filename, NULL, &ok);
3519
3520 if (!lookup_terrain(file, "warmer_wetter_result", filename, pterrain,
3521 &pterrain->warmer_wetter_result, TRUE)
3522 || !lookup_terrain(file, "warmer_drier_result", filename, pterrain,
3523 &pterrain->warmer_drier_result, TRUE)
3524 || !lookup_terrain(file, "cooler_wetter_result", filename, pterrain,
3525 &pterrain->cooler_wetter_result, TRUE)
3526 || !lookup_terrain(file, "cooler_drier_result", filename, pterrain,
3527 &pterrain->cooler_drier_result, TRUE)) {
3528 ok = FALSE;
3529 break;
3530 }
3531
3532 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsection);
3533 BV_CLR_ALL(pterrain->flags);
3534 for (j = 0; j < nval; j++) {
3535 const char *sval = slist[j];
3536 enum terrain_flag_id flag
3537 = terrain_flag_id_by_name(sval, fc_strcasecmp);
3538
3539 if (!terrain_flag_id_is_valid(flag)) {
3541 "\"%s\" [%s] has unknown flag \"%s\".",
3542 filename, tsection, sval);
3543 ok = FALSE;
3544 break;
3545 } else {
3546 BV_SET(pterrain->flags, flag);
3547 }
3548 }
3549 free(slist);
3550
3551 if (!ok) {
3552 break;
3553 }
3554
3555 {
3556 enum mapgen_terrain_property mtp;
3557 for (mtp = mapgen_terrain_property_begin();
3558 mtp != mapgen_terrain_property_end();
3559 mtp = mapgen_terrain_property_next(mtp)) {
3560 pterrain->property[mtp]
3561 = secfile_lookup_int_default(file, 0, "%s.property_%s", tsection,
3562 mapgen_terrain_property_name(mtp));
3563 }
3564 }
3565
3566 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
3567 BV_CLR_ALL(pterrain->native_to);
3568 for (j = 0; j < nval; j++) {
3569 struct unit_class *class = unit_class_by_rule_name(slist[j]);
3570
3571 if (!class) {
3573 "\"%s\" [%s] is native to unknown unit class \"%s\".",
3574 filename, tsection, slist[j]);
3575 ok = FALSE;
3576 break;
3577 } else {
3578 BV_SET(pterrain->native_to, uclass_index(class));
3579 }
3580 }
3581 free(slist);
3582
3583 if (!ok) {
3584 break;
3585 }
3586
3587 /* get terrain color */
3588 {
3589 fc_assert_ret_val(pterrain->rgb == NULL, FALSE);
3590 if (!rgbcolor_load(file, &pterrain->rgb, "%s.color", tsection)) {
3592 "Missing terrain color definition: %s",
3593 secfile_error());
3594 ok = FALSE;
3595 break;
3596 }
3597 }
3598
3599 pterrain->helptext = lookup_strvec(file, tsection, "helptext");
3601 }
3602
3603 if (ok) {
3604 /* extra details */
3605 extra_type_iterate(pextra) {
3606 BV_CLR_ALL(pextra->conflicts);
3608
3609 extra_type_iterate(pextra) {
3610 const char *section = &extra_sections[extra_index(pextra) * MAX_SECTION_LABEL];
3611 const char **slist;
3612 struct requirement_vector *reqs;
3613 const char *catname;
3614 int cj;
3615 enum extra_cause cause;
3616 enum extra_rmcause rmcause;
3617 const char *eus_name;
3618 const char *vis_req_name;
3619 const struct advance *vis_req;
3620
3621 catname = secfile_lookup_str(file, "%s.category", section);
3622 if (catname == NULL) {
3624 "\"%s\" extra \"%s\" has no category.",
3625 filename, extra_rule_name(pextra));
3626 ok = FALSE;
3627 break;
3628 }
3629 pextra->category = extra_category_by_name(catname, fc_strcasecmp);
3630 if (!extra_category_is_valid(pextra->category)) {
3632 "\"%s\" extra \"%s\" has invalid category \"%s\".",
3633 filename, extra_rule_name(pextra), catname);
3634 ok = FALSE;
3635 break;
3636 }
3637
3638 slist = secfile_lookup_str_vec(file, &nval, "%s.causes", section);
3639 pextra->causes = 0;
3640 for (cj = 0; cj < nval; cj++) {
3641 const char *sval = slist[cj];
3642
3643 cause = extra_cause_by_name(sval, fc_strcasecmp);
3644
3645 if (!extra_cause_is_valid(cause)) {
3647 "\"%s\" extra \"%s\": unknown cause \"%s\".",
3648 filename, extra_rule_name(pextra), sval);
3649 ok = FALSE;
3650 break;
3651 } else {
3652 pextra->causes |= (1 << cause);
3653 extra_to_caused_by_list(pextra, cause);
3654 }
3655 }
3656
3657 if (pextra->causes == 0) {
3658 /* Extras that do not have any causes added to EC_NONE list */
3660 }
3661
3662 if (!is_extra_caused_by(pextra, EC_BASE)
3663 && !is_extra_caused_by(pextra, EC_ROAD)
3664 && !is_extra_caused_by(pextra, EC_RESOURCE)) {
3665 /* Not a base, road, nor resource, so special */
3666 pextra->data.special_idx = extra_type_list_size(extra_type_list_by_cause(EC_SPECIAL));
3668 }
3669
3670 free(slist);
3671
3672 slist = secfile_lookup_str_vec(file, &nval, "%s.rmcauses", section);
3673 pextra->rmcauses = 0;
3674 for (j = 0; j < nval; j++) {
3675 const char *sval = slist[j];
3676
3677 rmcause = extra_rmcause_by_name(sval, fc_strcasecmp);
3678
3679 if (!extra_rmcause_is_valid(rmcause)) {
3681 "\"%s\" extra \"%s\": unknown rmcause \"%s\".",
3682 filename, extra_rule_name(pextra), sval);
3683 ok = FALSE;
3684 break;
3685 } else {
3686 pextra->rmcauses |= (1 << rmcause);
3687 extra_to_removed_by_list(pextra, rmcause);
3688 }
3689 }
3690
3691 free(slist);
3692
3693 sz_strlcpy(pextra->activity_gfx,
3695 "%s.activity_gfx", section));
3696 sz_strlcpy(pextra->act_gfx_alt,
3698 "%s.act_gfx_alt", section));
3699 sz_strlcpy(pextra->act_gfx_alt2,
3701 "%s.act_gfx_alt2", section));
3702 sz_strlcpy(pextra->rmact_gfx,
3704 "%s.rmact_gfx", section));
3705 sz_strlcpy(pextra->rmact_gfx_alt,
3707 "%s.rmact_gfx_alt", section));
3708 sz_strlcpy(pextra->graphic_str,
3709 secfile_lookup_str_default(file, "-", "%s.graphic", section));
3710 sz_strlcpy(pextra->graphic_alt,
3712 "%s.graphic_alt", section));
3713
3714 reqs = lookup_req_list(file, compat, section, "reqs", extra_rule_name(pextra));
3715 if (reqs == NULL) {
3716 ok = FALSE;
3717 break;
3718 }
3719 requirement_vector_copy(&pextra->reqs, reqs);
3720
3721 reqs = lookup_req_list(file, compat, section, "rmreqs", extra_rule_name(pextra));
3722 if (reqs == NULL) {
3723 ok = FALSE;
3724 break;
3725 }
3726 requirement_vector_copy(&pextra->rmreqs, reqs);
3727
3728 reqs = lookup_req_list(file, compat, section, "appearance_reqs", extra_rule_name(pextra));
3729 if (reqs == NULL) {
3730 ok = FALSE;
3731 break;
3732 }
3733 requirement_vector_copy(&pextra->appearance_reqs, reqs);
3734
3735 reqs = lookup_req_list(file, compat, section, "disappearance_reqs", extra_rule_name(pextra));
3736 if (reqs == NULL) {
3737 ok = FALSE;
3738 break;
3739 }
3740 requirement_vector_copy(&pextra->disappearance_reqs, reqs);
3741
3742 pextra->buildable = secfile_lookup_bool_default(file,
3744 "%s.buildable", section);
3745 pextra->generated = secfile_lookup_bool_default(file, TRUE,
3746 "%s.generated", section);
3747
3748 pextra->build_time = 0; /* default */
3749 lookup_time(file, &pextra->build_time, section, "build_time",
3750 filename, extra_rule_name(pextra), &ok);
3751 pextra->build_time_factor = secfile_lookup_int_default(file, 1,
3752 "%s.build_time_factor", section);
3753 pextra->removal_time = 0; /* default */
3754 lookup_time(file, &pextra->removal_time, section, "removal_time",
3755 filename, extra_rule_name(pextra), &ok);
3756 pextra->removal_time_factor = secfile_lookup_int_default(file, 1,
3757 "%s.removal_time_factor", section);
3758 pextra->infracost = secfile_lookup_int_default(file, 0,
3759 "%s.infracost", section);
3760 if (pextra->infracost > 0) {
3761 terrain_control.infrapoints = TRUE;
3762 }
3763
3764 pextra->defense_bonus = secfile_lookup_int_default(file, 0,
3765 "%s.defense_bonus",
3766 section);
3767 if (pextra->defense_bonus != 0) {
3768 if (extra_has_flag(pextra, EF_NATURAL_DEFENSE)) {
3770 } else {
3772 }
3773 }
3774
3775 eus_name = secfile_lookup_str_default(file, "Normal", "%s.unit_seen", section);
3776 pextra->eus = extra_unit_seen_type_by_name(eus_name, fc_strcasecmp);
3777 if (!extra_unit_seen_type_is_valid(pextra->eus)) {
3779 "\"%s\" extra \"%s\" has illegal unit_seen value \"%s\".",
3780 filename, extra_rule_name(pextra), eus_name);
3781 ok = FALSE;
3782 break;
3783 }
3784 if (pextra->eus == EUS_HIDDEN) {
3785 extra_type_list_append(extra_type_list_of_unit_hiders(), pextra);
3786 }
3787
3788 pextra->appearance_chance = secfile_lookup_int_default(file, RS_DEFAULT_EXTRA_APPEARANCE,
3789 "%s.appearance_chance",
3790 section);
3791 pextra->disappearance_chance = secfile_lookup_int_default(file,
3793 "%s.disappearance_chance",
3794 section);
3795
3796 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
3797 BV_CLR_ALL(pextra->native_to);
3798 for (j = 0; j < nval; j++) {
3799 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
3800
3801 if (uclass == NULL) {
3803 "\"%s\" extra \"%s\" is native to unknown unit class \"%s\".",
3804 filename, extra_rule_name(pextra), slist[j]);
3805 ok = FALSE;
3806 break;
3807 } else {
3808 BV_SET(pextra->native_to, uclass_index(uclass));
3809 }
3810 }
3811 free(slist);
3812
3813 if (!ok) {
3814 break;
3815 }
3816
3817 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
3818 BV_CLR_ALL(pextra->flags);
3819 for (j = 0; j < nval; j++) {
3820 const char *sval = slist[j];
3821 enum extra_flag_id flag = extra_flag_id_by_name(sval, fc_strcasecmp);
3822
3823 if (!extra_flag_id_is_valid(flag)) {
3825 "\"%s\" extra \"%s\": unknown flag \"%s\".",
3826 filename, extra_rule_name(pextra), sval);
3827 ok = FALSE;
3828 break;
3829 } else {
3830 BV_SET(pextra->flags, flag);
3831 }
3832 }
3833 free(slist);
3834
3835 if (extra_has_flag(pextra, EF_NOT_AGGRESSIVE)) {
3837 }
3838
3839 if (!ok) {
3840 break;
3841 }
3842
3843 slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
3844 for (j = 0; j < nval; j++) {
3845 const char *sval = slist[j];
3846 struct extra_type *pextra2 = extra_type_by_rule_name(sval);
3847
3848 if (pextra2 == NULL) {
3850 "\"%s\" extra \"%s\": unknown conflict extra \"%s\".",
3851 filename, extra_rule_name(pextra), sval);
3852 ok = FALSE;
3853 break;
3854 } else {
3855 BV_SET(pextra->conflicts, extra_index(pextra2));
3856 BV_SET(pextra2->conflicts, extra_index(pextra));
3857 }
3858 }
3859
3860 free(slist);
3861
3862 if (!ok) {
3863 break;
3864 }
3865
3866 slist = secfile_lookup_str_vec(file, &nval, "%s.hidden_by", section);
3867 BV_CLR_ALL(pextra->hidden_by);
3868 for (j = 0; j < nval; j++) {
3869 const char *sval = slist[j];
3870 const struct extra_type *top = extra_type_by_rule_name(sval);
3871
3872 if (top == NULL) {
3874 "\"%s\" extra \"%s\" hidden by unknown extra \"%s\".",
3875 filename, extra_rule_name(pextra), sval);
3876 ok = FALSE;
3877 break;
3878 } else {
3879 BV_SET(pextra->hidden_by, extra_index(top));
3880 }
3881 }
3882 free(slist);
3883
3884 if (!ok) {
3885 break;
3886 }
3887
3888 slist = secfile_lookup_str_vec(file, &nval, "%s.bridged_over", section);
3889 BV_CLR_ALL(pextra->bridged_over);
3890 for (j = 0; j < nval; j++) {
3891 const char *sval = slist[j];
3892 const struct extra_type *top = extra_type_by_rule_name(sval);
3893
3894 if (top == NULL) {
3896 "\"%s\" extra \"%s\" bridged over unknown extra \"%s\".",
3897 filename, extra_rule_name(pextra), sval);
3898 ok = FALSE;
3899 break;
3900 } else {
3901 BV_SET(pextra->bridged_over, extra_index(top));
3902 }
3903 }
3904 free(slist);
3905
3906 if (!ok) {
3907 break;
3908 }
3909
3910 vis_req_name = secfile_lookup_str_default(file, "None",
3911 "%s.visibility_req", section);
3912 vis_req = advance_by_rule_name(vis_req_name);
3913
3914 if (vis_req == NULL) {
3916 "\"%s\" %s: unknown visibility_req %s.",
3917 filename, section, vis_req_name);
3918 ok = FALSE;
3919 break;
3920 }
3921
3922 pextra->visibility_req = advance_number(vis_req);
3923
3924 pextra->helptext = lookup_strvec(file, section, "helptext");
3925
3928 }
3929
3930 if (ok) {
3931 int i = 0;
3932 /* resource details */
3933
3934 extra_type_by_cause_iterate(EC_RESOURCE, presource) {
3935 char identifier[MAX_LEN_NAME];
3936 const char *rsection = &resource_sections[i * MAX_SECTION_LABEL];
3937
3938 if (!presource->data.resource) {
3940 "\"%s\" extra \"%s\" has \"Resource\" cause but no "
3941 "corresponding [resource_*] section",
3942 filename, extra_rule_name(presource));
3943 ok = FALSE;
3944 break;
3945 }
3946
3948 presource->data.resource->output[o] =
3949 secfile_lookup_int_default(file, 0, "%s.%s", rsection,
3952
3953 sz_strlcpy(identifier,
3954 secfile_lookup_str(file, "%s.identifier", rsection));
3955 presource->data.resource->id_old_save = identifier[0];
3956 if (RESOURCE_NULL_IDENTIFIER == presource->data.resource->id_old_save) {
3958 "\"%s\" [%s] identifier missing value.",
3959 filename, rsection);
3960 ok = FALSE;
3961 break;
3962 }
3963 if (RESOURCE_NONE_IDENTIFIER == presource->data.resource->id_old_save) {
3965 "\"%s\" [%s] cannot use '%c' as an identifier;"
3966 " it is reserved.",
3967 filename, rsection, presource->data.resource->id_old_save);
3968 ok = FALSE;
3969 break;
3970 }
3971
3972 if (!ok) {
3973 break;
3974 }
3975
3976 i++;
3978
3979 for (j = 0; ok && j < game.control.num_resource_types; j++) {
3980 const char *section = &resource_sections[j * MAX_SECTION_LABEL];
3981 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
3982 struct extra_type *pextra = extra_type_by_rule_name(extra_name);
3983
3984 if (!is_extra_caused_by(pextra, EC_RESOURCE)) {
3986 "\"%s\" resource section [%s]: extra \"%s\" does not "
3987 "have \"Resource\" in its causes",
3988 filename, section, extra_name);
3989 ok = FALSE;
3990 }
3991 }
3992 }
3993
3994 if (ok) {
3995 /* This can't be part of previous loop as we don't want random data from previous
3996 * ruleset to play havoc on us when we have only some resource identifiers loaded
3997 * from the new ruleset. */
3998 extra_type_by_cause_iterate(EC_RESOURCE, pres) {
3999 extra_type_by_cause_iterate(EC_RESOURCE, pres2) {
4000 if (pres->data.resource->id_old_save == pres2->data.resource->id_old_save
4001 && pres != pres2) {
4003 "\"%s\" [%s] has the same identifier as [%s].",
4004 filename,
4005 extra_rule_name(pres),
4006 extra_rule_name(pres2));
4007 ok = FALSE;
4008 break;
4009 }
4011
4012 if (!ok) {
4013 break;
4014 }
4016 }
4017
4018 if (ok) {
4019 /* base details */
4020 extra_type_by_cause_iterate(EC_BASE, pextra) {
4021 struct base_type *pbase = extra_base_get(pextra);
4022 const char *section;
4023 const char *gui_str;
4024
4025 if (!pbase) {
4027 "\"%s\" extra \"%s\" has \"Base\" cause but no "
4028 "corresponding [base_*] section",
4029 filename, extra_rule_name(pextra));
4030 ok = FALSE;
4031 break;
4032 }
4034
4035 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4036 pbase->gui_type = base_gui_type_by_name(gui_str, fc_strcasecmp);
4037 if (!base_gui_type_is_valid(pbase->gui_type)) {
4039 "\"%s\" base \"%s\": unknown gui_type \"%s\".",
4040 filename, extra_rule_name(pextra), gui_str);
4041 ok = FALSE;
4042 break;
4043 }
4044
4045 pbase->border_sq = secfile_lookup_int_default(file, -1, "%s.border_sq",
4046 section);
4048 "%s.vision_main_sq",
4049 section);
4051 "%s.vision_invis_sq",
4052 section);
4054 "%s.vision_subs_sq",
4055 section);
4056
4057 if (compat->compat_mode) {
4058 int bj;
4059 const char **slist;
4060
4061 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
4062 for (bj = 0; bj < nval; bj++) {
4063 const char *sval = slist[bj];
4064
4065 if (fc_strcasecmp("NoAggressive", sval)) {
4067 "\"%s\" base \"%s\": unknown flag \"%s\".",
4068 filename, extra_rule_name(pextra), sval);
4069 ok = FALSE;
4070 break;
4071 } else {
4072 if (!BV_ISSET(pextra->flags, EF_NOT_AGGRESSIVE)) {
4073 /* We would not be adding extra to caused_by_list second time. */
4074 BV_SET(pextra->flags, EF_NOT_AGGRESSIVE);
4076 }
4077 }
4078 }
4079
4080 free(slist);
4081 }
4082
4083 if (!ok) {
4084 break;
4085 }
4086
4087 if (territory_claiming_base(pbase)) {
4088 extra_type_list_append(extra_type_list_of_terr_claimers(), pextra);
4089
4090 extra_type_by_cause_iterate(EC_BASE, pextra2) {
4091 struct base_type *pbase2;
4092
4093 if (pextra == pextra2) {
4094 /* End of the fully initialized bases iteration. */
4095 break;
4096 }
4097
4098 pbase2 = extra_base_get(pextra2);
4099 if (territory_claiming_base(pbase2)) {
4100 BV_SET(pextra->conflicts, extra_index(pextra2));
4101 BV_SET(pextra2->conflicts, extra_index(pextra));
4102 }
4104 }
4106
4107 for (j = 0; ok && j < game.control.num_base_types; j++) {
4108 const char *section = &base_sections[j * MAX_SECTION_LABEL];
4109 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4110 struct extra_type *pextra = extra_type_by_rule_name(extra_name);
4111
4112 if (!is_extra_caused_by(pextra, EC_BASE)) {
4114 "\"%s\" base section [%s]: extra \"%s\" does not have "
4115 "\"Base\" in its causes",
4116 filename, section, extra_name);
4117 ok = FALSE;
4118 }
4119 }
4120 }
4121
4122 if (ok) {
4123 bv_extras compat_bridged;
4124
4125 if (compat->compat_mode) {
4126 BV_CLR_ALL(compat_bridged);
4127 extra_type_by_cause_iterate(EC_ROAD, pextra) {
4128 struct road_type *proad = extra_road_get(pextra);
4129 const char *section = &road_sections[road_number(proad) * MAX_SECTION_LABEL];
4130 const char **slist;
4131
4132 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
4133
4134 for (j = 0; j < nval; j++) {
4135 if (!fc_strcasecmp("PreventsOtherRoads", slist[j])) {
4136 BV_SET(compat_bridged, pextra->id);
4137 }
4138 }
4140 }
4141 extra_type_by_cause_iterate(EC_ROAD, pextra) {
4142 struct road_type *proad = extra_road_get(pextra);
4143 const char *section;
4144 const char **slist;
4145 const char *special;
4146 const char *modestr;
4147 struct requirement_vector *reqs;
4148 const char *gui_str;
4149
4150 if (!proad) {
4152 "\"%s\" extra \"%s\" has \"Road\" cause but no "
4153 "corresponding [road_*] section",
4154 filename, extra_rule_name(pextra));
4155 ok = FALSE;
4156 break;
4157 }
4159
4160 reqs = lookup_req_list(file, compat, section, "first_reqs", extra_rule_name(pextra));
4161 if (reqs == NULL) {
4162 ok = FALSE;
4163 break;
4164 }
4165 requirement_vector_copy(&proad->first_reqs, reqs);
4166
4167 if (!secfile_lookup_int(file, &proad->move_cost,
4168 "%s.move_cost", section)) {
4169 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4170 ok = FALSE;
4171 break;
4172 }
4173
4174 modestr = secfile_lookup_str_default(file, "FastAlways", "%s.move_mode",
4175 section);
4176 proad->move_mode = road_move_mode_by_name(modestr, fc_strcasecmp);
4177 if (!road_move_mode_is_valid(proad->move_mode)) {
4179 "Illegal move_mode \"%s\" for road \"%s\"",
4180 modestr, extra_rule_name(pextra));
4181 ok = FALSE;
4182 break;
4183 }
4184
4186 proad->tile_incr_const[o] =
4187 secfile_lookup_int_default(file, 0, "%s.%s_incr_const",
4189 proad->tile_incr[o] =
4190 secfile_lookup_int_default(file, 0, "%s.%s_incr",
4192 proad->tile_bonus[o] =
4193 secfile_lookup_int_default(file, 0, "%s.%s_bonus",
4196
4197 special = secfile_lookup_str_default(file, "None", "%s.compat_special", section);
4198 if (!fc_strcasecmp(special, "Road")) {
4199 if (compat_road) {
4201 "Multiple roads marked as compatibility \"Road\"");
4202 ok = FALSE;
4203 }
4204 compat_road = TRUE;
4205 proad->compat = ROCO_ROAD;
4206 } else if (!fc_strcasecmp(special, "Railroad")) {
4207 if (compat_rail) {
4209 "Multiple roads marked as compatibility \"Railroad\"");
4210 ok = FALSE;
4211 }
4212 compat_rail = TRUE;
4213 proad->compat = ROCO_RAILROAD;
4214 } else if (!fc_strcasecmp(special, "River")) {
4215 if (compat_river) {
4217 "Multiple roads marked as compatibility \"River\"");
4218 ok = FALSE;
4219 }
4220 compat_river = TRUE;
4221 proad->compat = ROCO_RIVER;
4222 } else if (!fc_strcasecmp(special, "None")) {
4223 proad->compat = ROCO_NONE;
4224 } else {
4226 "Illegal compatibility special \"%s\" for road %s",
4227 special, extra_rule_name(pextra));
4228 ok = FALSE;
4229 }
4230
4231 if (!ok) {
4232 break;
4233 }
4234
4235 gui_str = secfile_lookup_str_default(file, NULL, "%s.gui_type", section);
4236 if (gui_str == NULL) {
4237 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
4238 proad->gui_type = rscompat_road_gui_type_3_1(proad);
4239 } else {
4241 "\"%s\" road \"%s\": no gui_type.",
4242 filename, extra_rule_name(pextra));
4243 ok = FALSE;
4244 break;
4245 }
4246 } else {
4247 proad->gui_type = road_gui_type_by_name(gui_str, fc_strcasecmp);
4248 if (!road_gui_type_is_valid(proad->gui_type)) {
4250 "\"%s\" road \"%s\": unknown gui_type \"%s\".",
4251 filename, extra_rule_name(pextra), gui_str);
4252 ok = FALSE;
4253 break;
4254 }
4255 }
4256
4257 slist = secfile_lookup_str_vec(file, &nval, "%s.integrates", section);
4258 BV_CLR_ALL(proad->integrates);
4259 for (j = 0; j < nval; j++) {
4260 const char *sval = slist[j];
4261 struct extra_type *textra = extra_type_by_rule_name(sval);
4262 struct road_type *top = NULL;
4263
4264 if (textra != NULL) {
4265 top = extra_road_get(textra);
4266 }
4267
4268 if (top == NULL) {
4270 "\"%s\" road \"%s\" integrates with unknown road \"%s\".",
4271 filename, extra_rule_name(pextra), sval);
4272 ok = FALSE;
4273 break;
4274 } else {
4275 BV_SET(proad->integrates, road_number(top));
4276 }
4277 }
4278 free(slist);
4279
4280 if (!ok) {
4281 break;
4282 }
4283
4284 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
4285 BV_CLR_ALL(proad->flags);
4286 for (j = 0; j < nval; j++) {
4287 const char *sval = slist[j];
4288
4289 if (compat->compat_mode && !fc_strcasecmp("PreventsOtherRoads", sval)) {
4290 /* Nothing to do here */
4291 } else if (compat->compat_mode && !fc_strcasecmp("RequiresBridge", sval)) {
4292 extra_type_iterate(pbridged) {
4293 if (BV_ISSET(compat_bridged, pbridged->id)) {
4294 BV_SET(pextra->bridged_over, pbridged->id);
4295 }
4297 } else {
4298 enum road_flag_id flag = road_flag_id_by_name(sval, fc_strcasecmp);
4299
4300 if (!road_flag_id_is_valid(flag)) {
4302 "\"%s\" road \"%s\": unknown flag \"%s\".",
4303 filename, extra_rule_name(pextra), sval);
4304 ok = FALSE;
4305 break;
4306 } else {
4307 BV_SET(proad->flags, flag);
4308 }
4309 }
4310 }
4311 free(slist);
4312
4313 if (!ok) {
4314 break;
4315 }
4317
4318 for (j = 0; ok && j < game.control.num_road_types; j++) {
4319 const char *section = &road_sections[j * MAX_SECTION_LABEL];
4320 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4321 struct extra_type *pextra = extra_type_by_rule_name(extra_name);
4322
4323 if (!is_extra_caused_by(pextra, EC_ROAD)) {
4325 "\"%s\" road section [%s]: extra \"%s\" does not have "
4326 "\"Road\" in its causes",
4327 filename, section, extra_name);
4328 ok = FALSE;
4329 }
4330 }
4331 }
4332
4333 if (ok) {
4334 extra_type_iterate(pextra) {
4335 pextra->bridged = extra_type_list_new();
4336 extra_type_iterate(pbridged) {
4337 if (BV_ISSET(pextra->bridged_over, pbridged->id)) {
4338 extra_type_list_append(pextra->bridged, pbridged);
4339 }
4342 }
4343
4344 if (ok) {
4346 }
4347
4348 return ok;
4349}
4350
4351/**********************************************************************/
4355static bool load_government_names(struct section_file *file,
4356 struct rscompat_info *compat)
4357{
4358 int nval = 0;
4359 struct section_list *sec;
4360 const char *filename = secfile_name(file);
4361 bool ok = TRUE;
4362
4363 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4364 return FALSE;
4365 }
4366
4367 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4368 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4369
4371 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
4372 ruleset_error(NULL, LOG_ERROR, "\"%s\": No governments?!?", filename);
4373 ok = FALSE;
4374 } else if (nval > G_LAST) {
4376 "\"%s\": Too many governments (%d, max %d)",
4377 filename, nval, G_LAST);
4378 ok = FALSE;
4379 }
4380
4381 if (ok) {
4382 governments_alloc(nval);
4383
4384 /* Government names are needed early so that get_government_by_name will
4385 * work. */
4386 governments_iterate(gov) {
4387 const char *sec_name =
4388 section_name(section_list_get(sec, government_index(gov)));
4389
4390 if (!ruleset_load_names(&gov->name, NULL, file, sec_name)) {
4391 ok = FALSE;
4392 break;
4393 }
4395 }
4396
4397 section_list_destroy(sec);
4398
4399 if (ok) {
4401 nval = (NULL != sec ? section_list_size(sec) : 0);
4402
4403 if (nval > MAX_NUM_MULTIPLIERS) {
4405 "\"%s\": Too many multipliers (%d, max %d)",
4406 filename, nval, MAX_NUM_MULTIPLIERS);
4407
4408 ok = FALSE;
4409 } else {
4411 }
4412
4413 if (ok) {
4414 multipliers_iterate(pmul) {
4415 const char *sec_name =
4416 section_name(section_list_get(sec, multiplier_index(pmul)));
4417
4418 if (!ruleset_load_names(&pmul->name, NULL, file, sec_name)) {
4420 "\"%s\": Cannot load multiplier names",
4421 filename);
4422 ok = FALSE;
4423 break;
4424 }
4426 }
4427 }
4428
4429 section_list_destroy(sec);
4430
4431 return ok;
4432}
4433
4434/**********************************************************************/
4438 struct rscompat_info *compat)
4439{
4440 struct section_list *sec;
4441 const char *filename = secfile_name(file);
4442 bool ok = TRUE;
4443
4445
4447 = lookup_government(file, "governments.during_revolution", filename, NULL);
4448 if (game.government_during_revolution == NULL) {
4449 ok = FALSE;
4450 }
4451
4452 if (ok) {
4455
4456 /* easy ones: */
4458 const int i = government_index(g);
4459 const char *sec_name = section_name(section_list_get(sec, i));
4460 struct requirement_vector *reqs =
4461 lookup_req_list(file, compat, sec_name, "reqs", government_rule_name(g));
4462
4463 if (reqs == NULL) {
4464 ok = FALSE;
4465 break;
4466 }
4467
4468 if (NULL != secfile_entry_lookup(file, "%s.ai_better", sec_name)) {
4469 char entry[100];
4470
4471 fc_snprintf(entry, sizeof(entry), "%s.ai_better", sec_name);
4472 g->ai.better = lookup_government(file, entry, filename, NULL);
4473 if (g->ai.better == NULL) {
4474 ok = FALSE;
4475 break;
4476 }
4477 } else {
4478 g->ai.better = NULL;
4479 }
4480 requirement_vector_copy(&g->reqs, reqs);
4481
4482 sz_strlcpy(g->graphic_str,
4483 secfile_lookup_str(file, "%s.graphic", sec_name));
4484 sz_strlcpy(g->graphic_alt,
4485 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
4486
4487 g->helptext = lookup_strvec(file, sec_name, "helptext");
4489 }
4490
4491
4492 if (ok) {
4493 /* titles */
4495 const char *sec_name =
4496 section_name(section_list_get(sec, government_index(g)));
4497 const char *male, *female;
4498
4499 if (!(male = secfile_lookup_str(file, "%s.ruler_male_title", sec_name))
4500 || !(female = secfile_lookup_str(file, "%s.ruler_female_title",
4501 sec_name))) {
4503 "Lack of default ruler titles for "
4504 "government \"%s\" (nb %d): %s",
4506 secfile_error());
4507 ok = FALSE;
4508 break;
4509 } else if (NULL == government_ruler_title_new(g, NULL, male, female)) {
4511 "Lack of default ruler titles for "
4512 "government \"%s\" (nb %d).",
4514 ok = FALSE;
4515 break;
4516 }
4518 }
4519
4520 section_list_destroy(sec);
4521
4522 if (ok) {
4524 multipliers_iterate(pmul) {
4525 int id = multiplier_index(pmul);
4526 const char *sec_name = section_name(section_list_get(sec, id));
4527 struct requirement_vector *reqs;
4528
4529 if (!secfile_lookup_int(file, &pmul->start, "%s.start", sec_name)) {
4530 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4531 ok = FALSE;
4532 break;
4533 }
4534 if (!secfile_lookup_int(file, &pmul->stop, "%s.stop", sec_name)) {
4535 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4536 ok = FALSE;
4537 break;
4538 }
4539 if (pmul->stop <= pmul->start) {
4541 "Multiplier \"%s\" stop (%d) must be greater "
4542 "than start (%d)", multiplier_rule_name(pmul),
4543 pmul->stop, pmul->start);
4544 ok = FALSE;
4545 break;
4546 }
4547 if (!secfile_lookup_int(file, &pmul->step, "%s.step", sec_name)) {
4548 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4549 ok = FALSE;
4550 break;
4551 }
4552 if (((pmul->stop - pmul->start) % pmul->step) != 0) {
4554 "Multiplier \"%s\" step (%d) does not fit "
4555 "exactly into interval start-stop (%d to %d)",
4556 multiplier_rule_name(pmul), pmul->step,
4557 pmul->start, pmul->stop);
4558 ok = FALSE;
4559 break;
4560 }
4561 if (!secfile_lookup_int(file, &pmul->def, "%s.default", sec_name)) {
4562 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4563 ok = FALSE;
4564 break;
4565 }
4566 if (pmul->def < pmul->start || pmul->def > pmul->stop) {
4568 "Multiplier \"%s\" default (%d) not within "
4569 "legal range (%d to %d)", multiplier_rule_name(pmul),
4570 pmul->def, pmul->start, pmul->stop);
4571 ok = FALSE;
4572 break;
4573 }
4574 if (((pmul->def - pmul->start) % pmul->step) != 0) {
4576 "Multiplier \"%s\" default (%d) not legal "
4577 "with respect to step size %d",
4578 multiplier_rule_name(pmul), pmul->def, pmul->step);
4579 ok = FALSE;
4580 break;
4581 }
4582 pmul->offset = secfile_lookup_int_default(file, 0,
4583 "%s.offset", sec_name);
4584 pmul->factor = secfile_lookup_int_default(file, 100,
4585 "%s.factor", sec_name);
4586 if (pmul->factor == 0) {
4588 "Multiplier \"%s\" scaling factor must "
4589 "not be zero", multiplier_rule_name(pmul));
4590 ok = FALSE;
4591 break;
4592 }
4593
4594 pmul->minimum_turns = secfile_lookup_int_default(file, 0,
4595 "%s.minimum_turns",
4596 sec_name);
4597
4598 reqs = lookup_req_list(file, compat, sec_name, "reqs",
4599 multiplier_rule_name(pmul));
4600 if (reqs == NULL) {
4601 ok = FALSE;
4602 break;
4603 }
4604 requirement_vector_copy(&pmul->reqs, reqs);
4605
4606 pmul->helptext = lookup_strvec(file, sec_name, "helptext");
4608 section_list_destroy(sec);
4609 }
4610
4611 if (ok) {
4613 }
4614
4615 return ok;
4616}
4617
4618/**********************************************************************/
4629static void send_ruleset_control(struct conn_list *dest)
4630{
4631 int desc_left = game.control.desc_length32;
4632 int idx = 0;
4633
4636
4637 if (game.ruleset_summary != NULL) {
4638 struct packet_ruleset_summary summary;
4639
4641
4642 lsend_packet_ruleset_summary(dest, &summary);
4643 }
4644
4645 while (desc_left > 0) {
4647 int this_len = desc_left;
4648
4649 if (this_len > MAX_LEN_CONTENT - 21) {
4650 this_len = MAX_LEN_CONTENT - 1;
4651 }
4652
4653 part.text[this_len] = '\0';
4654
4655 strncpy(part.text, &game.ruleset_description[idx], this_len);
4656 idx += this_len;
4657 desc_left -= this_len;
4658
4660 }
4661}
4662
4663/**********************************************************************/
4668static const char *check_leader_names(struct nation_type *pnation)
4669{
4670 nation_leader_list_iterate(nation_leaders(pnation), pleader) {
4671 const char *name = nation_leader_name(pleader);
4672
4673 nation_leader_list_iterate(nation_leaders(pnation), prev_leader) {
4674 if (prev_leader == pleader) {
4675 break;
4676 } else if (0 == fc_strcasecmp(name, nation_leader_name(prev_leader))) {
4677 return name;
4678 }
4681 return NULL;
4682}
4683
4684/**********************************************************************/
4688static bool load_nation_names(struct section_file *file,
4689 struct rscompat_info *compat)
4690{
4691 struct section_list *sec;
4692 int j;
4693 bool ok = TRUE;
4694 const char *filename = secfile_name(file);
4695
4696 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4697 return FALSE;
4698 }
4699
4700 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4701 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4702
4704 if (NULL == sec) {
4706 "No available nations in this ruleset!");
4707 ok = FALSE;
4708 } else if (section_list_size(sec) > MAX_NUM_NATIONS) {
4710 "Too many nations (max %d, we have %d)!",
4711 MAX_NUM_NATIONS, section_list_size(sec));
4712 ok = FALSE;
4713 } else {
4714 game.control.nation_count = section_list_size(sec);
4716
4717 nations_iterate(pl) {
4718 const int i = nation_index(pl);
4719 const char *sec_name = section_name(section_list_get(sec, i));
4720 const char *domain = secfile_lookup_str_default(file, NULL,
4721 "%s.translation_domain", sec_name);
4722 const char *noun_plural = secfile_lookup_str(file,
4723 "%s.plural", sec_name);
4724
4725
4726 if (domain == NULL) {
4727 domain = "freeciv-nations";
4728 }
4729
4730 if (!strcmp("freeciv-core", domain)) {
4731 pl->translation_domain = NULL;
4732 } else if (compat->compat_mode && compat->version < RSFORMAT_3_1
4733 && !strcmp("freeciv", domain)) {
4734 pl->translation_domain = NULL;
4735 } else if (!strcmp("freeciv-nations", domain)) {
4736 pl->translation_domain = fc_strdup(domain);
4737 } else {
4739 "Unsupported translation domain \"%s\" for %s",
4740 domain, sec_name);
4741 ok = FALSE;
4742 break;
4743 }
4744
4745 if (!ruleset_load_names(&pl->adjective, pl->translation_domain, file, sec_name)) {
4746 ok = FALSE;
4747 break;
4748 }
4749 name_set(&pl->noun_plural, pl->translation_domain, noun_plural);
4750
4751 /* Check if nation name is already defined. */
4752 for (j = 0; j < i && ok; j++) {
4753 struct nation_type *n2 = nation_by_number(j);
4754
4755 /* Compare strings after stripping off qualifiers -- we don't want
4756 * two nations to end up with identical adjectives displayed to users.
4757 * (This check only catches English, not localisations, of course.) */
4758 if (0 == strcmp(Qn_(untranslated_name(&n2->adjective)),
4759 Qn_(untranslated_name(&pl->adjective)))) {
4761 "Two nations defined with the same adjective \"%s\": "
4762 "in section \'%s\' and section \'%s\'",
4763 Qn_(untranslated_name(&pl->adjective)),
4764 section_name(section_list_get(sec, j)), sec_name);
4765 ok = FALSE;
4766 } else if (!strcmp(rule_name_get(&n2->adjective),
4767 rule_name_get(&pl->adjective))) {
4768 /* We cannot have the same rule name, as the game needs them to be
4769 * distinct. */
4771 "Two nations defined with the same rule_name \"%s\": "
4772 "in section \'%s\' and section \'%s\'",
4773 rule_name_get(&pl->adjective),
4774 section_name(section_list_get(sec, j)), sec_name);
4775 ok = FALSE;
4776 } else if (0 == strcmp(Qn_(untranslated_name(&n2->noun_plural)),
4777 Qn_(untranslated_name(&pl->noun_plural)))) {
4778 /* We don't want identical English plural names either. */
4780 "Two nations defined with the same plural name \"%s\": "
4781 "in section \'%s\' and section \'%s\'",
4782 Qn_(untranslated_name(&pl->noun_plural)),
4783 section_name(section_list_get(sec, j)), sec_name);
4784 ok = FALSE;
4785 }
4786 }
4787 if (!ok) {
4788 break;
4789 }
4791 }
4792
4793 section_list_destroy(sec);
4794
4795 if (ok) {
4797 if (sec != NULL) {
4798 game.control.num_nation_groups = section_list_size(sec);
4799
4800 section_list_iterate(sec, psection) {
4801 struct nation_group *pgroup;
4802 const char *name;
4803
4804 name = secfile_lookup_str(file, "%s.name", section_name(psection));
4805 if (NULL == name) {
4806 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4807 ok = FALSE;
4808 break;
4809 }
4810 pgroup = nation_group_new(name);
4811 if (pgroup == NULL) {
4812 ok = FALSE;
4813 break;
4814 }
4816 section_list_destroy(sec);
4817 sec = NULL;
4818 }
4819 }
4820
4821 return ok;
4822}
4823
4824/**********************************************************************/
4827static bool is_on_allowed_list(const char *name, const char **list, size_t len)
4828{
4829 int i;
4830
4831 for (i = 0; i < len; i++) {
4832 if (!fc_strcasecmp(name, list[i])) {
4833 return TRUE;
4834 }
4835 }
4836 return FALSE;
4837}
4838
4839/**********************************************************************/
4843static bool load_city_name_list(struct section_file *file,
4844 struct nation_type *pnation,
4845 const char *secfile_str1,
4846 const char *secfile_str2,
4847 const char **allowed_terrains,
4848 size_t atcount)
4849{
4850 size_t dim, j;
4851 bool ok = TRUE;
4852 const char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
4853 secfile_str1, secfile_str2);
4854
4855 /* Each string will be of the form "<cityname> (<label>, <label>, ...)".
4856 * The cityname is just the name for this city, while each "label" matches
4857 * a terrain type for the city (or "river"), with a preceeding ! to negate
4858 * it. The parentheses are optional (but necessary to have the settings,
4859 * of course). Our job is now to parse it. */
4860 for (j = 0; j < dim; j++) {
4861 size_t len = strlen(cities[j]);
4862 char city_name[len + 1], *p, *next, *end;
4863 struct nation_city *pncity;
4864
4865 sz_strlcpy(city_name, cities[j]);
4866
4867 /* Now we wish to determine values for all of the city labels. A value
4868 * of NCP_NONE means no preference (which is necessary so that the use
4869 * of this is optional); NCP_DISLIKE means the label is negated and
4870 * NCP_LIKE means it's labelled. Mostly the parsing just involves
4871 * a lot of ugly string handling... */
4872 if ((p = strchr(city_name, '('))) {
4873 *p++ = '\0';
4874
4875 if (!(end = strchr(p, ')'))) {
4877 "\"%s\" [%s] %s: city name \"%s\" "
4878 "unmatched parenthesis.", secfile_name(file),
4879 secfile_str1, secfile_str2, cities[j]);
4880 ok = FALSE;
4881 } else {
4882 for (*end++ = '\0'; '\0' != *end; end++) {
4883 if (!fc_isspace(*end)) {
4885 "\"%s\" [%s] %s: city name \"%s\" "
4886 "contains characters after last parenthesis.",
4887 secfile_name(file), secfile_str1, secfile_str2,
4888 cities[j]);
4889 ok = FALSE;
4890 break;
4891 }
4892 }
4893 }
4894 }
4895
4896 /* Build the nation_city. */
4898 if (check_cityname(city_name)) {
4899 /* The ruleset contains a name that is too long. This shouldn't
4900 * happen - if it does, the author should get immediate feedback. */
4902 "\"%s\" [%s] %s: city name \"%s\" is too long.",
4903 secfile_name(file),
4904 secfile_str1, secfile_str2, city_name);
4905 ok = FALSE;
4906 city_name[MAX_LEN_CITYNAME - 1] = '\0';
4907 }
4908 pncity = nation_city_new(pnation, city_name);
4909
4910 if (NULL != p) {
4911 /* Handle the labels one at a time. */
4912 do {
4913 enum nation_city_preference prefer;
4914
4915 if ((next = strchr(p, ','))) {
4916 *next = '\0';
4917 }
4919
4920 /* The ! is used to mark a negative, which is recorded with
4921 * NCP_DISLIKE. Otherwise we use a NCP_LIKE.
4922 */
4923 if (*p == '!') {
4924 p++;
4925 prefer = NCP_DISLIKE;
4926 } else {
4927 prefer = NCP_LIKE;
4928 }
4929
4930 if (0 == fc_strcasecmp(p, "river")) {
4932 && !is_on_allowed_list(p,
4933 game.server.ruledit.allowed_terrains, atcount)) {
4935 "\"%s\" [%s] %s: city \"%s\" "
4936 "has terrain hint \"%s\" not in allowed_terrains.",
4937 secfile_name(file), secfile_str1, secfile_str2,
4938 city_name, p);
4939 ok = FALSE;
4940 } else {
4941 nation_city_set_river_preference(pncity, prefer);
4942 }
4943 } else {
4944 const struct terrain *pterrain = terrain_by_rule_name(p);
4945
4946 if (NULL == pterrain) {
4947 /* Try with removing frequent trailing 's'. */
4948 size_t l = strlen(p);
4949
4950 if (0 < l && 's' == fc_tolower(p[l - 1])) {
4951 char saved = p[l - 1];
4952
4953 p[l - 1] = '\0';
4954 pterrain = terrain_by_rule_name(p);
4955 if (pterrain == NULL) {
4956 /* Didn't help, restore for later allowed_terrains check */
4957 p[l - 1] = saved;
4958 }
4959 }
4960 }
4961
4962 /* Nationset may have been devised with a specific set of terrains
4963 * in mind which don't quite match this ruleset, in which case we
4964 * (a) quietly ignore any hints mentioned that don't happen to be in
4965 * the current ruleset, (b) enforce that terrains mentioned by nations
4966 * must be on the list */
4967 if (pterrain != NULL && game.server.ruledit.allowed_terrains != NULL) {
4968 if (!is_on_allowed_list(p,
4969 game.server.ruledit.allowed_terrains, atcount)) {
4970 /* Terrain exists, but not intended for these nations */
4972 "\"%s\" [%s] %s: city \"%s\" "
4973 "has terrain hint \"%s\" not in allowed_terrains.",
4974 secfile_name(file), secfile_str1, secfile_str2,
4975 city_name, p);
4976 ok = FALSE;
4977 break;
4978 }
4979 } else if (!pterrain) {
4980 /* Terrain doesn't exist; only complain if it's not on any list */
4982 || !is_on_allowed_list(p,
4983 game.server.ruledit.allowed_terrains, atcount)) {
4985 "\"%s\" [%s] %s: city \"%s\" "
4986 "has unknown terrain hint \"%s\".",
4987 secfile_name(file), secfile_str1, secfile_str2,
4988 city_name, p);
4989 ok = FALSE;
4990 break;
4991 }
4992 }
4993 if (NULL != pterrain) {
4994 nation_city_set_terrain_preference(pncity, pterrain, prefer);
4995 }
4996 }
4997
4998 p = next ? next + 1 : NULL;
4999 } while (NULL != p && '\0' != *p);
5000 }
5001 }
5002
5003 if (NULL != cities) {
5004 free(cities);
5005 }
5006
5007 return ok;
5008}
5009
5010/**********************************************************************/
5013static bool load_ruleset_nations(struct section_file *file,
5014 struct rscompat_info *compat)
5015{
5016 struct government *gov;
5017 int j;
5018 size_t dim;
5019 char temp_name[MAX_LEN_NAME];
5020 const char **vec;
5021 const char *name, *bad_leader;
5022 const char *sval;
5023 int default_set;
5024 const char *filename = secfile_name(file);
5025 struct section_list *sec = NULL;
5026 enum trait tr;
5027 bool ok = TRUE;
5028
5029 name = secfile_lookup_str_default(file, NULL, "ruledit.nationlist");
5030 if (name != NULL) {
5032 }
5034 "ruledit.embedded_nations");
5035
5036 if (vec != NULL) {
5037 /* Copy to persistent vector */
5040
5041 for (j = 0; j < game.server.ruledit.embedded_nations_count; j++) {
5043 }
5044
5045 free(vec);
5046 }
5047
5048 game.default_government = NULL;
5049
5050 ruleset_load_traits(game.server.default_traits, file, "default_traits", "");
5051 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5052 if (game.server.default_traits[tr].min < 0) {
5054 }
5055 if (game.server.default_traits[tr].max < 0) {
5057 }
5058 if (game.server.default_traits[tr].fixed < 0) {
5060
5061 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5063 }
5066 "Default values for trait %s not sane.",
5067 trait_name(tr));
5068 ok = FALSE;
5069 break;
5070 }
5071 }
5072
5073 if (ok) {
5075 "compatibility.allowed_govs");
5076 if (vec != NULL) {
5077 /* Copy to persistent vector */
5079 = fc_malloc(game.server.ruledit.ag_count * sizeof(char *));
5081 (const char **)game.server.ruledit.nc_agovs;
5082
5083 for (j = 0; j < game.server.ruledit.ag_count; j++) {
5085 }
5086
5087 free(vec);
5088 }
5089
5091 "compatibility.allowed_terrains");
5092 if (vec != NULL) {
5093 /* Copy to persistent vector */
5095 = fc_malloc(game.server.ruledit.at_count * sizeof(char *));
5097 (const char **)game.server.ruledit.nc_aterrs;
5098
5099 for (j = 0; j < game.server.ruledit.at_count; j++) {
5101 }
5102
5103 free(vec);
5104 }
5105
5107 "compatibility.allowed_styles");
5108 if (vec != NULL) {
5109 /* Copy to persistent vector */
5111 = fc_malloc(game.server.ruledit.as_count * sizeof(char *));
5113 (const char **)game.server.ruledit.nc_astyles;
5114
5115 for (j = 0; j < game.server.ruledit.as_count; j++) {
5117 }
5118
5119 free(vec);
5120 }
5121
5122 sval = secfile_lookup_str_default(file, NULL,
5123 "compatibility.default_government");
5124 /* We deliberately don't check this against allowed_govs. It's only
5125 * specified once so not vulnerable to typos, and may usefully be set in
5126 * a specific ruleset to a gov not explicitly known by the nation set. */
5127 if (sval != NULL) {
5129 if (game.default_government == NULL) {
5131 "Tried to set unknown government type \"%s\" as default_government!",
5132 sval);
5133 ok = FALSE;
5134 } else {
5137 }
5138 }
5139 }
5140
5141 if (ok) {
5143 if (sec != NULL) {
5144 game.control.num_nation_sets = section_list_size(sec);
5145
5146 section_list_iterate(sec, psection) {
5147 const char *set_name, *set_rule_name, *set_description;
5148
5149 set_name = secfile_lookup_str(file, "%s.name", section_name(psection));
5150 set_rule_name =
5151 secfile_lookup_str(file, "%s.rule_name", section_name(psection));
5152 set_description = secfile_lookup_str_default(file, "", "%s.description",
5153 section_name(psection));
5154 if (NULL == set_name || NULL == set_rule_name) {
5155 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5156 ok = FALSE;
5157 break;
5158 }
5159 if (nation_set_new(set_name, set_rule_name, set_description) == NULL) {
5160 ok = FALSE;
5161 break;
5162 }
5164 section_list_destroy(sec);
5165 sec = NULL;
5166 } else {
5168 "At least one nation set [" NATION_SET_SECTION_PREFIX "_*] "
5169 "must be defined.");
5170 ok = FALSE;
5171 }
5172 }
5173
5174 if (ok) {
5175 /* Default set that every nation is a member of. */
5176 sval = secfile_lookup_str_default(file, NULL,
5177 "compatibility.default_nationset");
5178 if (sval != NULL) {
5179 const struct nation_set *pset = nation_set_by_rule_name(sval);
5180 if (pset != NULL) {
5181 default_set = nation_set_number(pset);
5182 } else {
5184 "Unknown default_nationset \"%s\".", sval);
5185 ok = FALSE;
5186 }
5187 } else if (nation_set_count() == 1) {
5188 /* If there's only one set defined, every nation is implicitly a
5189 * member of that set. */
5190 default_set = 0;
5191 } else {
5192 /* No default nation set; every nation must explicitly specify at
5193 * least one set to be a member of. */
5194 default_set = -1;
5195 }
5196 }
5197
5198 if (ok) {
5200 if (sec) {
5201 section_list_iterate(sec, psection) {
5202 struct nation_group *pgroup;
5203 bool hidden;
5204
5205 name = secfile_lookup_str(file, "%s.name", section_name(psection));
5207 if (pgroup == NULL) {
5208 ok = FALSE;
5209 break;
5210 }
5211
5212 hidden = secfile_lookup_bool_default(file, FALSE, "%s.hidden",
5213 section_name(psection));
5215
5216 if (!secfile_lookup_int(file, &j, "%s.match", section_name(psection))) {
5217 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5218 ok = FALSE;
5219 break;
5220 }
5221 nation_group_set_match(pgroup, j);
5223 section_list_destroy(sec);
5224 sec = NULL;
5225 }
5226 }
5227
5228 if (ok) {
5230 nations_iterate(pnation) {
5231 struct nation_type *pconflict;
5232 const int i = nation_index(pnation);
5233 char tmp[200] = "\0";
5234 const char *barb_type;
5235 const char *sec_name = section_name(section_list_get(sec, i));
5236 const char *legend;
5237
5238 /* Nation sets and groups. */
5239 if (default_set >= 0) {
5240 nation_set_list_append(pnation->sets,
5241 nation_set_by_number(default_set));
5242 }
5243 vec = secfile_lookup_str_vec(file, &dim, "%s.groups", sec_name);
5244 for (j = 0; j < dim; j++) {
5245 struct nation_set *pset = nation_set_by_rule_name(vec[j]);
5246 struct nation_group *pgroup = nation_group_by_rule_name(vec[j]);
5247
5248 fc_assert(pset == NULL || pgroup == NULL);
5249
5250 if (NULL != pset) {
5251 nation_set_list_append(pnation->sets, pset);
5252 } else if (NULL != pgroup) {
5253 nation_group_list_append(pnation->groups, pgroup);
5254 } else {
5255 /* For nation authors, this would probably be considered an error.
5256 * But it can happen normally. The civ1 compatibility ruleset only
5257 * uses the nations that were in civ1, so not all of the links will
5258 * exist. */
5259 log_verbose("Nation %s: Unknown set/group \"%s\".",
5260 nation_rule_name(pnation), vec[j]);
5261 }
5262 }
5263 if (NULL != vec) {
5264 free(vec);
5265 }
5266 if (nation_set_list_size(pnation->sets) < 1) {
5268 "Nation %s is not a member of any nation set",
5269 nation_rule_name(pnation));
5270 ok = FALSE;
5271 break;
5272 }
5273
5274 /* Nation conflicts. */
5275 vec = secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec_name);
5276 for (j = 0; j < dim; j++) {
5277 pconflict = nation_by_rule_name(vec[j]);
5278
5279 if (pnation == pconflict) {
5281 "Nation %s conflicts with itself",
5282 nation_rule_name(pnation));
5283 ok = FALSE;
5284 break;
5285 } else if (NULL != pconflict) {
5286 nation_list_append(pnation->server.conflicts_with, pconflict);
5287 } else {
5288 /* For nation authors, this would probably be considered an error.
5289 * But it can happen normally. The civ1 compatibility ruleset only
5290 * uses the nations that were in civ1, so not all of the links will
5291 * exist. */
5292 log_verbose("Nation %s: conflicts_with nation \"%s\" is unknown.",
5293 nation_rule_name(pnation), vec[j]);
5294 }
5295 }
5296 if (NULL != vec) {
5297 free(vec);
5298 }
5299 if (!ok) {
5300 break;
5301 }
5302
5303 /* Nation leaders. */
5304 for (j = 0; j < MAX_NUM_LEADERS; j++) {
5305 const char *sex;
5306 bool is_male = FALSE;
5307
5308 name = secfile_lookup_str(file, "%s.leaders%d.name", sec_name, j);
5309 if (NULL == name) {
5310 /* No more to read. */
5311 break;
5312 }
5313
5314 if (check_name(name)) {
5315 /* The ruleset contains a name that is too long. This shouldn't
5316 * happen - if it does, the author should get immediate feedback */
5317 sz_strlcpy(temp_name, name);
5319 "Nation %s: leader name \"%s\" is too long.",
5320 nation_rule_name(pnation), name);
5321 ok = FALSE;
5322 break;
5323 }
5324
5325 sex = secfile_lookup_str(file, "%s.leaders%d.sex", sec_name, j);
5326 if (NULL == sex) {
5327 ruleset_error(NULL, LOG_ERROR, "Nation %s: leader \"%s\": %s.",
5328 nation_rule_name(pnation), name, secfile_error());
5329 ok = FALSE;
5330 break;
5331 } else if (0 == fc_strcasecmp("Male", sex)) {
5332 is_male = TRUE;
5333 } else if (0 != fc_strcasecmp("Female", sex)) {
5335 "Nation %s: leader \"%s\" has unsupported "
5336 "sex variant \"%s\".",
5337 nation_rule_name(pnation), name, sex);
5338 ok = FALSE;
5339 break;
5340 }
5341 (void) nation_leader_new(pnation, name, is_male);
5342 }
5343 if (!ok) {
5344 break;
5345 }
5346
5347 /* Check the number of leaders. */
5348 if (MAX_NUM_LEADERS == j) {
5349 /* Too much leaders, get the real number defined in the ruleset. */
5350 while (NULL != secfile_entry_lookup(file, "%s.leaders%d.name",
5351 sec_name, j)) {
5352 j++;
5353 }
5355 "Nation %s: Too many leaders; max is %d",
5357 ok = FALSE;
5358 break;
5359 } else if (0 == j) {
5361 "Nation %s: no leaders; at least one is required.",
5362 nation_rule_name(pnation));
5363 ok = FALSE;
5364 break;
5365 }
5366
5367 /* Check if leader name is not already defined in this nation. */
5368 if ((bad_leader = check_leader_names(pnation))) {
5370 "Nation %s: leader \"%s\" defined more than once.",
5371 nation_rule_name(pnation), bad_leader);
5372 ok = FALSE;
5373 break;
5374 }
5375
5376 /* Nation player color preference, if any */
5377 fc_assert_ret_val(pnation->server.rgb == NULL, FALSE);
5378 (void) rgbcolor_load(file, &pnation->server.rgb, "%s.color", sec_name);
5379
5380 /* Load nation traits */
5381 ruleset_load_traits(pnation->server.traits, file, sec_name, "trait_");
5382 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5383 bool server_traits_used = TRUE;
5384
5385 if (pnation->server.traits[tr].min < 0) {
5386 pnation->server.traits[tr].min = game.server.default_traits[tr].min;
5387 } else {
5388 server_traits_used = FALSE;
5389 }
5390 if (pnation->server.traits[tr].max < 0) {
5391 pnation->server.traits[tr].max = game.server.default_traits[tr].max;
5392 } else {
5393 server_traits_used = FALSE;
5394 }
5395 if (pnation->server.traits[tr].fixed < 0) {
5396 if (server_traits_used) {
5397 pnation->server.traits[tr].fixed = game.server.default_traits[tr].fixed;
5398 } else {
5399 int diff = pnation->server.traits[tr].max - pnation->server.traits[tr].min;
5400
5401 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5402 pnation->server.traits[tr].fixed = diff / 2 + pnation->server.traits[tr].min;
5403 }
5404 }
5405 if (pnation->server.traits[tr].max < pnation->server.traits[tr].min) {
5407 "%s values for trait %s not sane.",
5408 nation_rule_name(pnation), trait_name(tr));
5409 ok = FALSE;
5410 break;
5411 }
5412 }
5413
5414 if (!ok) {
5415 break;
5416 }
5417
5418 pnation->is_playable =
5419 secfile_lookup_bool_default(file, TRUE, "%s.is_playable", sec_name);
5420
5421 /* Check barbarian type. Default is "None" meaning not a barbarian */
5422 barb_type = secfile_lookup_str_default(file, "None",
5423 "%s.barbarian_type", sec_name);
5424 pnation->barb_type = barbarian_type_by_name(barb_type, fc_strcasecmp);
5425 if (!barbarian_type_is_valid(pnation->barb_type)) {
5427 "Nation %s, barbarian_type is invalid (\"%s\")",
5428 nation_rule_name(pnation), barb_type);
5429 ok = FALSE;
5430 break;
5431 }
5432
5433 if (pnation->barb_type != NOT_A_BARBARIAN
5434 && pnation->is_playable) {
5435 /* We can't allow players to use barbarian nations, barbarians
5436 * may run out of nations */
5438 "Nation %s marked both barbarian and playable.",
5439 nation_rule_name(pnation));
5440 ok = FALSE;
5441 break;
5442 }
5443
5444 /* Flags */
5445 sz_strlcpy(pnation->flag_graphic_str,
5446 secfile_lookup_str_default(file, "-", "%s.flag", sec_name));
5447 sz_strlcpy(pnation->flag_graphic_alt,
5449 "%s.flag_alt", sec_name));
5450
5451 /* Ruler titles */
5452 for (j = 0;; j++) {
5453 const char *male, *female;
5454
5455 name = secfile_lookup_str_default(file, NULL,
5456 "%s.ruler_titles%d.government",
5457 sec_name, j);
5458 if (NULL == name) {
5459 /* End of the list of ruler titles. */
5460 break;
5461 }
5462
5463 /* NB: even if the government doesn't exist, we load the entries for
5464 * the ruler titles to avoid warnings about unused entries. */
5465 male = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
5466 sec_name, j);
5467 female = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
5468 sec_name, j);
5470
5471 /* Nationset may have been devised with a specific set of govs in
5472 * mind which don't quite match this ruleset, in which case we
5473 * (a) quietly ignore any govs mentioned that don't happen to be in
5474 * the current ruleset, (b) enforce that govs mentioned by nations
5475 * must be on the list */
5476 if (gov != NULL && game.server.ruledit.allowed_govs != NULL) {
5480 /* Gov exists, but not intended for these nations */
5481 gov = NULL;
5483 "Nation %s: government \"%s\" not in allowed_govs.",
5484 nation_rule_name(pnation), name);
5485 ok = FALSE;
5486 break;
5487 }
5488 } else if (!gov) {
5489 /* Gov doesn't exist; only complain if it's not on any list */
5490 if (game.server.ruledit.allowed_govs == NULL
5495 "Nation %s: government \"%s\" not found.",
5496 nation_rule_name(pnation), name);
5497 ok = FALSE;
5498 break;
5499 }
5500 }
5501 if (NULL != male && NULL != female) {
5502 if (gov) {
5503 (void) government_ruler_title_new(gov, pnation, male, female);
5504 }
5505 } else {
5506 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
5507 ok = FALSE;
5508 break;
5509 }
5510 }
5511 if (!ok) {
5512 break;
5513 }
5514
5515 /* City styles */
5516 name = secfile_lookup_str(file, "%s.style", sec_name);
5517 if (!name) {
5518 ruleset_error(NULL, LOG_ERROR, "%s", secfile_error());
5519 ok = FALSE;
5520 break;
5521 }
5522 pnation->style = style_by_rule_name(name);
5523 if (pnation->style == NULL) {
5524 if (game.server.ruledit.allowed_styles == NULL
5529 "Nation %s: Illegal style \"%s\"",
5530 nation_rule_name(pnation), name);
5531 ok = FALSE;
5532 break;
5533 } else {
5534 log_verbose("Nation %s: style \"%s\" not supported in this "
5535 "ruleset; using default.",
5536 nation_rule_name(pnation), name);
5537 pnation->style = style_by_number(0);
5538 }
5539 }
5540
5541 /* Civilwar nations */
5542 vec = secfile_lookup_str_vec(file, &dim,
5543 "%s.civilwar_nations", sec_name);
5544 for (j = 0; j < dim; j++) {
5545 pconflict = nation_by_rule_name(vec[j]);
5546
5547 /* No test for duplicate nations is performed. If there is a duplicate
5548 * entry it will just cause that nation to have an increased
5549 * probability of being chosen. */
5550 if (pconflict == pnation) {
5552 "Nation %s is its own civil war nation",
5553 nation_rule_name(pnation));
5554 ok = FALSE;
5555 break;
5556 } else if (NULL != pconflict) {
5557 nation_list_append(pnation->server.civilwar_nations, pconflict);
5558 nation_list_append(pconflict->server.parent_nations, pnation);
5559 } else {
5560 /* For nation authors, this would probably be considered an error.
5561 * But it can happen normally. The civ1 compatibility ruleset only
5562 * uses the nations that were in civ1, so not all of the links will
5563 * exist. */
5564 log_verbose("Nation %s: civil war nation \"%s\" is unknown.",
5565 nation_rule_name(pnation), vec[j]);
5566 }
5567 }
5568 if (NULL != vec) {
5569 free(vec);
5570 }
5571 if (!ok) {
5572 break;
5573 }
5574
5575 /* Load nation specific initial items */
5576 if (!lookup_tech_list(file, sec_name, "init_techs",
5577 pnation->init_techs, filename)) {
5578 ok = FALSE;
5579 break;
5580 }
5581 if (!lookup_building_list(file, sec_name, "init_buildings",
5582 pnation->init_buildings, filename)) {
5583 ok = FALSE;
5584 break;
5585 }
5586 if (!lookup_unit_list(file, sec_name, "init_units",
5587 pnation->init_units, filename)) {
5588 ok = FALSE;
5589 break;
5590 }
5591 fc_strlcat(tmp, sec_name, 200);
5592 fc_strlcat(tmp, ".init_government", 200);
5593 if (secfile_entry_by_path(file, tmp)) {
5594 pnation->init_government = lookup_government(file, tmp, filename,
5595 NULL);
5596 /* If specified, init_government has to be in this specific ruleset,
5597 * not just allowed_govs */
5598 if (pnation->init_government == NULL) {
5599 ok = FALSE;
5600 break;
5601 }
5602 /* ...but if a list of govs has been specified, enforce that this
5603 * nation's init_government is on the list. */
5604 if (game.server.ruledit.allowed_govs != NULL
5605 && !is_on_allowed_list(government_rule_name(pnation->init_government),
5609 "Nation %s: init_government \"%s\" not allowed.",
5610 nation_rule_name(pnation),
5611 government_rule_name(pnation->init_government));
5612 ok = FALSE;
5613 break;
5614 }
5615 }
5616
5617 /* Read default city names. */
5618 if (!load_city_name_list(file, pnation, sec_name, "cities",
5621 ok = FALSE;
5622 break;
5623 }
5624
5625 legend = secfile_lookup_str_default(file, "", "%s.legend", sec_name);
5626 pnation->legend = fc_strdup(legend);
5627 if (check_strlen(pnation->legend, MAX_LEN_MSG, NULL)) {
5629 "Nation %s: legend \"%s\" is too long.",
5630 nation_rule_name(pnation),
5631 pnation->legend);
5632 ok = FALSE;
5633 break;
5634 }
5635
5636 pnation->player = NULL;
5638 section_list_destroy(sec);
5639 sec = NULL;
5640 }
5641
5642 /* Clean up on aborted load */
5643 if (sec != NULL) {
5644 fc_assert(!ok);
5645 section_list_destroy(sec);
5646 }
5647
5648 if (ok) {
5650 }
5651
5652 if (ok) {
5653 /* Update cached number of playable nations in the current set */
5655
5656 /* Sanity checks on all sets */
5657 nation_sets_iterate(pset) {
5658 int num_playable = 0, barb_land_count = 0, barb_sea_count = 0, barb_both_count = 0;
5659
5660 nations_iterate(pnation) {
5661 if (nation_is_in_set(pnation, pset)) {
5662 switch (nation_barbarian_type(pnation)) {
5663 case NOT_A_BARBARIAN:
5664 if (is_nation_playable(pnation)) {
5665 num_playable++;
5666 }
5667 break;
5668 case LAND_BARBARIAN:
5669 barb_land_count++;
5670 break;
5671 case SEA_BARBARIAN:
5672 barb_sea_count++;
5673 break;
5674 case ANIMAL_BARBARIAN:
5675 /* Animals are optional */
5676 break;
5677 case LAND_AND_SEA_BARBARIAN:
5678 barb_both_count++;
5679 break;
5680 default:
5682 }
5683 }
5685 if (num_playable < 1) {
5687 "Nation set \"%s\" has no playable nations. "
5688 "At least one required!", nation_set_rule_name(pset));
5689 ok = FALSE;
5690 break;
5691 }
5692 if (barb_land_count == 0 && barb_both_count == 0) {
5694 "No land barbarian nation defined in set \"%s\". "
5695 "At least one required!", nation_set_rule_name(pset));
5696 ok = FALSE;
5697 break;
5698 }
5699 if (barb_sea_count == 0 && barb_both_count == 0) {
5701 "No sea barbarian nation defined in set \"%s\". "
5702 "At least one required!", nation_set_rule_name(pset));
5703 ok = FALSE;
5704 break;
5705 }
5707 }
5708
5709 return ok;
5710}
5711
5712/**********************************************************************/
5716static bool load_style_names(struct section_file *file,
5717 struct rscompat_info *compat)
5718{
5719 bool ok = TRUE;
5720 struct section_list *sec;
5721 const char *filename = secfile_name(file);
5722
5723 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5724 return FALSE;
5725 }
5726
5727 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5728 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5729
5731 if (NULL == sec) {
5733 "No available nation styles in this ruleset!");
5734 ok = FALSE;
5735 } else {
5736 game.control.num_styles = section_list_size(sec);
5737
5739
5740 styles_iterate(ps) {
5741 const int i = style_index(ps);
5742 const char *sec_name = section_name(section_list_get(sec, i));
5743
5744 ruleset_load_names(&ps->name, NULL, file, sec_name);
5746 }
5747
5748 section_list_destroy(sec);
5749
5750 if (ok) {
5751 /* The citystyle sections: */
5752 int i = 0;
5753
5755 if (NULL != sec) {
5756 city_styles_alloc(section_list_size(sec));
5757 section_list_iterate(sec, style) {
5758 if (!ruleset_load_names(&city_styles[i].name, NULL, file, section_name(style))) {
5759 ok = FALSE;
5760 break;
5761 }
5762 i++;
5764
5765 section_list_destroy(sec);
5766 } else {
5768 }
5769 }
5770
5771 return ok;
5772}
5773
5774/**********************************************************************/
5777static bool load_ruleset_styles(struct section_file *file,
5778 struct rscompat_info *compat)
5779{
5780 struct section_list *sec;
5781 int i;
5782 bool ok = TRUE;
5783
5784 /* City Styles ... */
5785
5787
5788 /* Get rest: */
5789 for (i = 0; i < game.control.styles_count; i++) {
5790 struct requirement_vector *reqs;
5791 const char *sec_name = section_name(section_list_get(sec, i));
5792
5793 sz_strlcpy(city_styles[i].graphic,
5794 secfile_lookup_str(file, "%s.graphic", sec_name));
5795 sz_strlcpy(city_styles[i].graphic_alt,
5796 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
5797 sz_strlcpy(city_styles[i].citizens_graphic,
5799 "%s.citizens_graphic", sec_name));
5800
5801 reqs = lookup_req_list(file, compat, sec_name, "reqs", city_style_rule_name(i));
5802 if (reqs == NULL) {
5803 ok = FALSE;
5804 break;
5805 }
5806 requirement_vector_copy(&city_styles[i].reqs, reqs);
5807 }
5808
5809 section_list_destroy(sec);
5810
5811 if (ok) {
5813
5814 if (sec != NULL) {
5815 int musi;
5816
5817 game.control.num_music_styles = section_list_size(sec);
5819 musi = 0;
5820
5821 section_list_iterate(sec, psection) {
5822 struct requirement_vector *reqs;
5823 struct music_style *pmus = music_style_by_number(musi);
5824 const char *sec_name = section_name(psection);
5825
5828 "%s.music_peaceful", sec_name));
5831 "%s.music_combat", sec_name));
5832
5833 reqs = lookup_req_list(file, compat, sec_name, "reqs", "Music Style");
5834 if (reqs == NULL) {
5835 ok = FALSE;
5836 break;
5837 }
5838 requirement_vector_copy(&pmus->reqs, reqs);
5839
5840 musi++;
5842 }
5843
5844 section_list_destroy(sec);
5845 }
5846
5847 return ok;
5848}
5849
5850/**********************************************************************/
5856 struct action_auto_perf *auto_perf,
5857 const char *uflags_path,
5858 const char *filename)
5859{
5860 /* Add each listed protected unit type flag as a !present
5861 * requirement. */
5862 if (secfile_entry_lookup(file, "%s", uflags_path)) {
5863 enum unit_type_flag_id *protecor_flag;
5864 size_t psize;
5865 int i;
5866
5867 protecor_flag =
5868 secfile_lookup_enum_vec(file, &psize, unit_type_flag_id,
5869 "%s", uflags_path);
5870
5871 if (!protecor_flag) {
5872 /* Entity exists but couldn't read it. */
5874 "\"%s\": %s: bad unit type flag list.",
5875 filename, uflags_path);
5876
5877 return FALSE;
5878 }
5879
5880 for (i = 0; i < psize; i++) {
5881 requirement_vector_append(&auto_perf->reqs,
5882 req_from_values(VUT_UTFLAG,
5883 REQ_RANGE_LOCAL,
5884 FALSE, FALSE, TRUE,
5885 protecor_flag[i]));
5886 }
5887
5888 free(protecor_flag);
5889 }
5890
5891 return TRUE;
5892}
5893
5894/**********************************************************************/
5899 struct action_auto_perf *auto_perf,
5900 const char *actions_path,
5901 const char *filename)
5902{
5903 /* Read the alternative actions. */
5904 if (secfile_entry_lookup(file, "%s", actions_path)) {
5905 enum gen_action *unit_acts;
5906 size_t asize;
5907 int i;
5908
5909 unit_acts = secfile_lookup_enum_vec(file, &asize, gen_action,
5910 "%s", actions_path);
5911
5912 if (!unit_acts) {
5913 /* Entity exists but couldn't read it. */
5915 "\"%s\": %s: bad action list",
5916 filename, actions_path);
5917
5918 return FALSE;
5919 }
5920
5921 for (i = 0; i < asize; i++) {
5922 auto_perf->alternatives[i] = unit_acts[i];
5923 }
5924
5925 free(unit_acts);
5926 }
5927
5928 return TRUE;
5929}
5930
5931/**********************************************************************/
5935 struct action_auto_perf *auto_perf,
5936 const char *item,
5937 const char *filename)
5938{
5939 char uflags_path[100];
5940 char action_path[100];
5941
5942 fc_snprintf(uflags_path, sizeof(uflags_path),
5943 "missing_unit_upkeep.%s_protected", item);
5944 fc_snprintf(action_path, sizeof(action_path),
5945 "missing_unit_upkeep.%s_unit_act", item);
5946
5947 return (load_action_auto_uflag_block(file, auto_perf, uflags_path,
5948 filename)
5949 && load_action_auto_actions(file, auto_perf, action_path,
5950 filename));
5951}
5952
5953/**********************************************************************/
5956static bool load_ruleset_cities(struct section_file *file,
5957 struct rscompat_info *compat)
5958{
5959 const char *filename = secfile_name(file);
5960 const char *item;
5961 struct section_list *sec;
5962 bool ok = TRUE;
5963
5964 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5965 return FALSE;
5966 }
5967
5968 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5969 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5970
5971 /* Specialist options */
5973 if (section_list_size(sec) >= SP_MAX) {
5975 "\"%s\": Too many specialists (%d, max %d).",
5976 filename, section_list_size(sec), SP_MAX);
5977 ok = FALSE;
5978 }
5979
5980 if (ok) {
5981 int i = 0;
5982 const char *tag;
5983
5984 game.control.num_specialist_types = section_list_size(sec);
5985
5986 section_list_iterate(sec, psection) {
5987 struct specialist *s = specialist_by_number(i);
5988 struct requirement_vector *reqs;
5989 const char *sec_name = section_name(psection);
5990
5991 if (!ruleset_load_names(&s->name, NULL, file, sec_name)) {
5992 ok = FALSE;
5993 break;
5994 }
5995
5997 "%s.short_name", sec_name);
5998 name_set(&s->abbreviation, NULL, item);
5999
6000 tag = secfile_lookup_str(file, "%s.graphic", sec_name);
6001 if (tag == NULL) {
6003 "\"%s\": No graphic tag for specialist at %s.",
6004 filename, sec_name);
6005 ok = FALSE;
6006 break;
6007 }
6008 sz_strlcpy(s->graphic_str, tag);
6011 "%s.graphic_alt", sec_name));
6012
6013 reqs = lookup_req_list(file, compat, sec_name, "reqs", specialist_rule_name(s));
6014 if (reqs == NULL) {
6015 ok = FALSE;
6016 break;
6017 }
6018 requirement_vector_copy(&s->reqs, reqs);
6019
6020 s->helptext = lookup_strvec(file, sec_name, "helptext");
6021
6022 if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
6024 }
6025 i++;
6027 }
6028
6029 if (ok && DEFAULT_SPECIALIST == -1) {
6031 "\"%s\": must give a min_size of 0 for at least one "
6032 "specialist type.", filename);
6033 ok = FALSE;
6034 }
6035 section_list_destroy(sec);
6036 sec = NULL;
6037
6038 if (ok) {
6039 /* City Parameters */
6040
6043 "parameters.celebrate_size_limit");
6045 secfile_lookup_int_default(file, GAME_DEFAULT_ADDTOSIZE, "parameters.add_to_size_limit");
6048 "parameters.angry_citizens");
6049
6051 secfile_lookup_bool_default(file, GAME_DEFAULT_CHANGABLE_TAX, "parameters.changable_tax");
6053 secfile_lookup_int_default(file, 0, "parameters.forced_science");
6055 secfile_lookup_int_default(file, 100, "parameters.forced_luxury");
6057 secfile_lookup_int_default(file, 0, "parameters.forced_gold");
6059 + game.info.forced_gold != 100) {
6061 "\"%s\": Forced taxes do not add up in ruleset!",
6062 filename);
6063 ok = FALSE;
6064 }
6065 }
6066
6067 if (ok) {
6068 /* civ1 & 2 didn't reveal tiles */
6071 "parameters.vision_reveal_tiles");
6072
6074 secfile_lookup_int_default(file, 1, "parameters.pop_report_zeroes");
6075
6076 /* Citizens configuration. */
6079 "citizen.nationality");
6082 "citizen.convert_speed");
6084 secfile_lookup_int_default(file, 0, "citizen.partisans_pct");
6086 secfile_lookup_int_default(file, 0, "citizen.conquest_convert_pct");
6087 }
6088
6089 if (ok) {
6090 /* Missing unit upkeep. */
6091 struct action_auto_perf *auto_perf;
6092
6093 /* Can't pay food upkeep! */
6095 auto_perf->cause = AAPC_UNIT_UPKEEP;
6096
6097 /* This is about food upkeep. */
6098 requirement_vector_append(&auto_perf->reqs,
6099 req_from_str("OutputType", "Local",
6100 FALSE, TRUE, TRUE,
6101 "Food"));
6102
6103 /* Internally represented as an action auto performer rule. */
6104 if (!load_muuk_as_action_auto(file, auto_perf, "food", filename)) {
6105 ok = FALSE;
6106 }
6107
6110 "missing_unit_upkeep.food_wipe");
6111
6112 /* Can't pay gold upkeep! */
6114 auto_perf->cause = AAPC_UNIT_UPKEEP;
6115
6116 /* This is about gold upkeep. */
6117 requirement_vector_append(&auto_perf->reqs,
6118 req_from_str("OutputType", "Local",
6119 FALSE, TRUE, TRUE,
6120 "Gold"));
6121
6122 /* Internally represented as an action auto performer rule. */
6123 if (!load_muuk_as_action_auto(file, auto_perf, "gold", filename)) {
6124 ok = FALSE;
6125 }
6126
6129 "missing_unit_upkeep.gold_wipe");
6130
6131 /* Can't pay shield upkeep! */
6133 auto_perf->cause = AAPC_UNIT_UPKEEP;
6134
6135 /* This is about shield upkeep. */
6136 requirement_vector_append(&auto_perf->reqs,
6137 req_from_str("OutputType", "Local",
6138 FALSE, TRUE, TRUE,
6139 "Shield"));
6140
6141 /* Internally represented as an action auto performer rule. */
6142 if (!load_muuk_as_action_auto(file, auto_perf, "shield", filename)) {
6143 ok = FALSE;
6144 }
6145
6148 "missing_unit_upkeep.shield_wipe");
6149 }
6150
6151 if (ok) {
6153 }
6154
6155 return ok;
6156}
6157
6158/**********************************************************************/
6161static bool load_ruleset_effects(struct section_file *file,
6162 struct rscompat_info *compat)
6163{
6164 struct section_list *sec;
6165 const char *type;
6166 const char *filename;
6167 bool ok = TRUE;
6168
6169 filename = secfile_name(file);
6170
6171 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6172 return FALSE;
6173 }
6174
6175 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6176 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6177
6178 /* Parse effects and add them to the effects ruleset cache. */
6180 section_list_iterate(sec, psection) {
6181 enum effect_type eff;
6182 int value;
6183 struct multiplier *pmul;
6184 struct effect *peffect;
6185 const char *sec_name = section_name(psection);
6186 struct requirement_vector *reqs;
6187
6188 type = secfile_lookup_str(file, "%s.type", sec_name);
6189
6190 if (type == NULL) {
6192 "\"%s\" [%s] missing effect type.", filename, sec_name);
6193 ok = FALSE;
6194 break;
6195 }
6196
6197 if (compat->compat_mode && rscompat_old_effect_3_1(type, file, sec_name, compat)) {
6198 continue;
6199 }
6200
6201 eff = effect_type_by_name(type, fc_strcasecmp);
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) {
6217 pmul = multiplier_by_rule_name(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
6239 effect_req_append(peffect, *preq);
6241
6243 section_list_destroy(sec);
6244
6245 if (ok) {
6247 }
6248
6249 return ok;
6250}
6251
6252/**********************************************************************/
6255static int secfile_lookup_int_default_min_max(struct section_file *file,
6256 int def, int min, int max,
6257 const char *path, ...)
6258 fc__attribute((__format__ (__printf__, 5, 6)));
6260 int def, int min, int max,
6261 const char *path, ...)
6262{
6263 char fullpath[256];
6264 int ival;
6265 va_list args;
6266
6267 va_start(args, path);
6268 fc_vsnprintf(fullpath, sizeof(fullpath), path, args);
6269 va_end(args);
6270
6271 if (!secfile_lookup_int(file, &ival, "%s", fullpath)) {
6272 ival = def;
6273 }
6274
6275 if (ival < min) {
6277 "\"%s\" should be in the interval [%d, %d] "
6278 "but is %d; using the minimal value.",
6279 fullpath, min, max, ival);
6280 ival = min;
6281 }
6282
6283 if (ival > max) {
6285 "\"%s\" should be in the interval [%d, %d] "
6286 "but is %d; using the maximal value.",
6287 fullpath, min, max, ival);
6288 ival = max;
6289 }
6290
6291 return ival;
6292}
6293
6294/**********************************************************************/
6297static bool load_action_ui_name(struct section_file *file, int act,
6298 const char *entry_name,
6299 const char *compat_name)
6300{
6301 const char *text;
6302 const char *def = action_ui_name_default(act);
6303
6304 if (compat_name != NULL) {
6305 def = secfile_lookup_str_default(file, def,
6306 "actions.%s", compat_name);
6307 }
6308
6309 text = secfile_lookup_str_default(file, def,
6310 "actions.%s", entry_name);
6311 sz_strlcpy(action_by_number(act)->ui_name, text);
6312
6313 return TRUE;
6314}
6315
6316/**********************************************************************/
6320 struct section_file *file, action_id act)
6321{
6322 struct action *paction = action_by_number(act);
6323 const char *vname = action_max_range_ruleset_var_name(act);
6324
6325 if (vname != NULL) {
6326 struct entry *pentry;
6327 int max_range;
6328
6329 pentry = secfile_entry_lookup(file, "actions.%s", vname);
6330
6331 if (pentry == NULL) {
6332 const char *compat_name = rscompat_action_max_range_name_S3_1(compat, act);
6333
6334 if (compat_name != NULL) {
6335 pentry = secfile_entry_lookup(file, "actions.%s",
6336 compat_name);
6337 }
6338 }
6339
6340 if (pentry == NULL) {
6341 max_range = action_max_range_default(paction->result);
6342 } else {
6343 const char *custom;
6344
6345 if (entry_type_get(pentry) == ENTRY_INT
6346 && entry_int_get(pentry, &max_range)) {
6347 /* max_range already assigned */
6348 } else if (entry_type_get(pentry) == ENTRY_STR
6349 && entry_str_get(pentry, &custom)
6351 max_range = ACTION_DISTANCE_UNLIMITED;
6352 } else {
6353 ruleset_error(NULL, LOG_ERROR, "Bad actions.%s",
6356
6357 return FALSE;
6358 }
6359 }
6360
6361 action_by_number(act)->max_distance = max_range;
6362 }
6363
6364 return TRUE;
6365}
6366
6367/**********************************************************************/
6371 struct section_file *file, action_id act)
6372{
6373 struct action *paction = action_by_number(act);
6374 const char *vname;
6375
6376 if (!load_action_range_max(compat, file, act)) {
6377 return FALSE;
6378 }
6379
6381 if (vname != NULL) {
6382 /* Min range can be loaded from the ruleset. */
6386 "actions.%s",
6387 vname);
6388 }
6389
6390 return TRUE;
6391}
6392
6393/**********************************************************************/
6396static bool load_action_kind(struct section_file *file, action_id act)
6397{
6398 struct action *paction = action_by_number(act);
6399
6400 if (action_target_kind_ruleset_var_name(act) == NULL) {
6401 /* Target kind can't be loaded from the ruleset. */
6402 }
6403
6407 paction->result),
6408 action_target_kind,
6409 "actions.%s",
6411
6412 return TRUE;
6413}
6414
6415/**********************************************************************/
6419 action_id act)
6420{
6422 /* Actor consumption can be loaded from the ruleset. */
6425 file, RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS, "actions.%s",
6427 }
6428
6429 return TRUE;
6430}
6431
6432/**********************************************************************/
6436 const char *filename,
6437 struct action *paction)
6438{
6439 if (action_blocked_by_ruleset_var_name(paction) != NULL) {
6440 /* Action blocking can be loaded from the ruleset. */
6441
6442 char fullpath[1024];
6443
6444 fc_snprintf(fullpath, sizeof(fullpath), "actions.%s",
6446
6447 if (secfile_entry_by_path(file, fullpath)) {
6448 enum gen_action *blocking_actions;
6449 size_t asize;
6450 int j;
6451
6452 blocking_actions =
6453 secfile_lookup_enum_vec(file, &asize, gen_action, "%s", fullpath);
6454
6455 if (!blocking_actions) {
6456 /* Entity exists but couldn't read it. */
6458 "\"%s\": %s: bad action list",
6459 filename, fullpath);
6460
6461 return FALSE;
6462 }
6463
6464 for (j = 0; j < asize; j++) {
6465 BV_SET(paction->blocked_by, blocking_actions[j]);
6466 }
6467
6468 free(blocking_actions);
6469 }
6470 }
6471
6472 return TRUE;
6473}
6474
6475/**********************************************************************/
6480 const char *filename,
6481 int performer_slot,
6482 struct action *paction)
6483{
6484 struct action_auto_perf *auto_perf;
6485 char action_list_path[100];
6486
6487 if (action_post_success_forced_ruleset_var_name(paction) == NULL) {
6488 /* Not relevant. */
6489 return TRUE;
6490 }
6491
6492 auto_perf = action_auto_perf_slot_number(performer_slot);
6493 auto_perf->cause = AAPC_POST_ACTION;
6494
6495 /* Limit auto performer to this action. */
6496 requirement_vector_append(&auto_perf->reqs,
6497 req_from_values(VUT_ACTION, REQ_RANGE_LOCAL,
6498 FALSE, TRUE, TRUE,
6499 paction->id));
6500
6501 /* Load the list of actions. */
6502 fc_snprintf(action_list_path, sizeof(action_list_path),
6503 "actions.%s",
6505 if (!load_action_auto_actions(file, auto_perf,
6506 action_list_path, filename)) {
6507 return FALSE;
6508 }
6509
6510 return TRUE;
6511}
6512
6513/**********************************************************************/
6516static bool lookup_bv_actions(struct section_file *file,
6517 const char *filename,
6518 bv_actions *target,
6519 const char *path)
6520{
6521 if (secfile_entry_by_path(file, path)) {
6522 enum gen_action *listed_actions;
6523 size_t asize;
6524 int j;
6525
6526 listed_actions = secfile_lookup_enum_vec(file, &asize, gen_action,
6527 "%s", path);
6528
6529 if (!listed_actions) {
6530 /* Entity exists but couldn't read it. */
6531 ruleset_error(NULL, LOG_ERROR, "\"%s\": %s: bad action list",
6532 filename, path);
6533
6534 return FALSE;
6535 }
6536
6537 for (j = 0; j < asize; j++) {
6538 BV_SET(*target, listed_actions[j]);
6539 }
6540
6541 free(listed_actions);
6542 }
6543
6544 return TRUE;
6545}
6546
6547/**********************************************************************/
6550static bool load_ruleset_game(struct section_file *file, bool act,
6551 struct rscompat_info *compat)
6552{
6553 const char *sval, **svec;
6554 const char *filename;
6555 int *food_ini;
6556 int i;
6557 size_t teams;
6558 const char *pref_text;
6559 size_t gni_tmp;
6560 struct section_list *sec;
6561 size_t nval;
6562 const char *name;
6563 bool ok = TRUE;
6564
6565 if (file == NULL) {
6566 return FALSE;
6567 }
6568 filename = secfile_name(file);
6569
6570 name = secfile_lookup_str_default(file, NULL, "ruledit.description_file");
6571 if (name != NULL) {
6573 }
6574
6575 /* section: tileset */
6576 pref_text = secfile_lookup_str_default(file, "", "tileset.prefered");
6577 if (pref_text[0] != '\0') {
6578 log_deprecation("Entry tileset.prefered in game.ruleset."
6579 " Use correct spelling tileset.preferred instead");
6580 }
6581 pref_text = secfile_lookup_str_default(file, pref_text, "tileset.preferred");
6582 if (pref_text[0] != '\0') {
6583 /* There was tileset suggestion */
6585 } else {
6586 /* No tileset suggestions */
6587 game.control.preferred_tileset[0] = '\0';
6588 }
6589
6590 /* section: soundset */
6591 pref_text = secfile_lookup_str_default(file, "", "soundset.prefered");
6592 if (pref_text[0] != '\0') {
6593 log_deprecation("Entry soundset.prefered in game.ruleset."
6594 " Use correct spelling soundset.preferred instead");
6595 }
6596 pref_text = secfile_lookup_str_default(file, pref_text, "soundset.preferred");
6597 if (pref_text[0] != '\0') {
6598 /* There was soundset suggestion */
6600 } else {
6601 /* No soundset suggestions */
6603 }
6604
6605 /* section: musicset */
6606 pref_text = secfile_lookup_str_default(file, "", "musicset.prefered");
6607 if (pref_text[0] != '\0') {
6608 log_deprecation("Entry musicset.prefered in game.ruleset."
6609 " Use correct spelling musicset.preferred instead");
6610 }
6611 pref_text = secfile_lookup_str_default(file, pref_text, "musicset.preferred");
6612 if (pref_text[0] != '\0') {
6613 /* There was musicset suggestion */
6615 } else {
6616 /* No musicset suggestions */
6618 }
6619
6620 /* section: about */
6621 pref_text = secfile_lookup_str(file, "about.name");
6622 /* Ruleset/modpack name found */
6623 sz_strlcpy(game.control.name, pref_text);
6624
6625 pref_text = secfile_lookup_str_default(file, "", "about.version");
6626 if (pref_text[0] != '\0') {
6627 /* Ruleset/modpack version found */
6628 sz_strlcpy(game.control.version, pref_text);
6629 } else {
6630 /* No version information */
6631 game.control.version[0] = '\0';
6632 }
6633
6634 pref_text = secfile_lookup_str_default(file, "", "about.alt_dir");
6635 if (pref_text[0] != '\0') {
6636 /* Alt directory definition found. */
6637 sz_strlcpy(game.control.alt_dir, pref_text);
6638 } else {
6639 /* No alt directory information */
6640 game.control.alt_dir[0] = '\0';
6641 }
6642
6643 pref_text = secfile_lookup_str_default(file, "", "about.summary");
6644 if (pref_text[0] != '\0') {
6645 int len;
6646
6647 /* Ruleset/modpack summary found */
6648 len = strlen(pref_text);
6650 fc_strlcpy(game.ruleset_summary, pref_text, len + 1);
6651 } else {
6652 /* No summary */
6653 if (game.ruleset_summary != NULL) {
6654 free(game.ruleset_summary);
6655 game.ruleset_summary = NULL;
6656 }
6657 }
6658
6659 pref_text = secfile_lookup_str_default(file, "", "about.description");
6660 if (pref_text[0] != '\0') {
6661 int len;
6662
6663 /* Ruleset/modpack description found */
6664 len = strlen(pref_text);
6666 fc_strlcpy(game.ruleset_description, pref_text, len + 1);
6668 } else {
6669 /* No description */
6670 if (game.ruleset_description != NULL) {
6673 }
6675 }
6676
6677 pref_text = secfile_lookup_str_default(file, "", "about.capabilities");
6678 if (pref_text[0] != '\0') {
6679 int len = strlen(pref_text);
6680
6682 fc_strlcpy(game.ruleset_capabilities, pref_text, len +1);
6683 } else {
6685 game.ruleset_capabilities[0] = '\0';
6686 }
6687
6688 /* section: options */
6689 if (!lookup_tech_list(file, "options", "global_init_techs",
6690 game.rgame.global_init_techs, filename)) {
6691 ok = FALSE;
6692 }
6693
6694 if (ok) {
6695 if (!lookup_building_list(file, "options", "global_init_buildings",
6696 game.rgame.global_init_buildings, filename)) {
6697 ok = FALSE;
6698 }
6699 }
6700
6701 if (ok) {
6702 const char **slist;
6703 int j;
6704
6706 "options.popup_tech_help");
6707
6708 /* section: civstyle */
6711 "civstyle.base_pollution");
6712
6713 game.info.gameloss_style = GAMELOSS_STYLE_CLASSICAL;
6714
6715 slist = secfile_lookup_str_vec(file, &nval, "civstyle.gameloss_style");
6716 for (j = 0; j < nval; j++) {
6717 enum gameloss_style style;
6718
6719 sval = slist[j];
6720 if (strcmp(sval, "") == 0) {
6721 continue;
6722 }
6723 style = gameloss_style_by_name(sval, fc_strcasecmp);
6724 if (!gameloss_style_is_valid(style)) {
6726 "\"%s\": bad value \"%s\" for gameloss_style.",
6727 filename, sval);
6728 ok = FALSE;
6729 break;
6730 } else {
6731 game.info.gameloss_style |= style;
6732 }
6733 }
6734 free(slist);
6735 }
6736
6737 if (ok) {
6743 "civstyle.happy_cost");
6749 "civstyle.food_cost");
6751 = secfile_lookup_bool_default(file, TRUE, "civstyle.civil_war_enabled");
6752
6755 "civstyle.civil_war_bonus_celebrating");
6756
6759 "civstyle.civil_war_bonus_unhappy");
6760
6766 "civstyle.base_bribe_cost");
6772 "civstyle.ransom_gold");
6775 "civstyle.pillage_select");
6776
6779 "civstyle.tech_steal_allow_holes");
6782 "civstyle.tech_trade_allow_holes");
6785 "civstyle.tech_trade_loss_allow_holes");
6788 "civstyle.tech_parasite_allow_holes");
6791 "civstyle.tech_loss_allow_holes");
6792
6798 "civstyle.upgrade_veteran_loss");
6804 "civstyle.autoupgrade_veteran_loss");
6805
6811 "research.base_tech_cost");
6812
6813 food_ini = secfile_lookup_int_vec(file, &gni_tmp,
6814 "civstyle.granary_food_ini");
6815 game.info.granary_num_inis = (int) gni_tmp;
6816
6819 "Too many granary_food_ini entries (%d, max %d)",
6821 ok = FALSE;
6822 } else if (game.info.granary_num_inis == 0) {
6823 log_error("No values for granary_food_ini. Using default "
6824 "value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
6827 } else {
6828 int gi;
6829
6830 /* check for <= 0 entries */
6831 for (gi = 0; gi < game.info.granary_num_inis; gi++) {
6832 if (food_ini[gi] <= 0) {
6833 if (gi == 0) {
6834 food_ini[gi] = RS_DEFAULT_GRANARY_FOOD_INI;
6835 } else {
6836 food_ini[gi] = food_ini[gi - 1];
6837 }
6838 log_error("Bad value for granary_food_ini[%i]. Using %i.",
6839 gi, food_ini[gi]);
6840 }
6841 game.info.granary_food_ini[gi] = food_ini[gi];
6842 }
6843 }
6844 free(food_ini);
6845 }
6846
6847 if (ok) {
6853 "civstyle.granary_food_inc");
6854
6861 "civstyle.min_city_center_%s",
6864 }
6865
6866 if (ok) {
6867 const char *tus_text;
6868
6874 "civstyle.init_vis_radius_sq");
6875
6881 "civstyle.init_city_radius_sq");
6882
6884 "civstyle.gold_upkeep_style");
6885 game.info.gold_upkeep_style = gold_upkeep_style_by_name(tus_text,
6887 if (!gold_upkeep_style_is_valid(game.info.gold_upkeep_style)) {
6889 "Unknown gold upkeep style \"%s\"",
6890 tus_text);
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
6911 game.info.small_wonder_visibility = wonder_visib_type_by_name(text,
6913 if (!wonder_visib_type_is_valid(game.info.small_wonder_visibility)) {
6915 "Unknown wonder visibility typpe \"%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 if (ok) {
6977 /* Auto attack. */
6978 struct action_auto_perf *auto_perf;
6979
6980 /* Action auto performers aren't ready to be exposed in the ruleset
6981 * yet. The behavior when two action auto performers for the same
6982 * cause can fire isn't set in stone yet. How is one of them chosen?
6983 * What if all the actions of the chosen action auto performer turned
6984 * out to be illegal but one of the other action auto performers that
6985 * fired has legal actions? These issues can decide what other action
6986 * rules action auto performers can represent in the future. Deciding
6987 * should therefore wait until a rule needs action auto performers to
6988 * work a certain way. */
6989 /* Only one action auto performer, ACTION_AUTO_MOVED_ADJ, is caused
6990 * by AAPC_UNIT_MOVED_ADJ. It is therefore safe to expose the full
6991 * requirement vector to the ruleset. */
6992 struct requirement_vector *reqs;
6993
6994 /* A unit moved next to this unit and the autoattack server setting
6995 * is enabled. */
6997 auto_perf->cause = AAPC_UNIT_MOVED_ADJ;
6998
6999 reqs = lookup_req_list(file, compat,
7000 "auto_attack", "if_attacker",
7001 "auto_attack");
7002 if (reqs == NULL) {
7003 ok = FALSE;
7004 } else {
7005 requirement_vector_copy(&auto_perf->reqs, reqs);
7006
7007 if (!load_action_auto_actions(file, auto_perf,
7008 "auto_attack.attack_actions",
7009 filename)) {
7010 /* Failed to load auto attack actions */
7012 "\"%s\": %s: failed load %s.",
7013 filename, "auto_attack", "attack_actions");
7014 ok = FALSE;
7015 }
7016
7017 if (ok && compat->compat_mode) {
7018 enum unit_type_flag_id *protecor_flag;
7019 size_t psize;
7020
7021 if (secfile_entry_lookup(file, "%s", "auto_attack.will_never")) {
7022 protecor_flag =
7023 secfile_lookup_enum_vec(file, &psize, unit_type_flag_id,
7024 "%s", "auto_attack.will_never");
7025
7026 if (!protecor_flag) {
7027 /* Entity exists but couldn't read it. */
7029 "\"%s\": %s: bad unit type flag list.",
7030 filename, "auto_attack.will_never");
7031
7032 ok = FALSE;
7033 }
7034 } else {
7035 psize = 0;
7036 protecor_flag = NULL;
7037 }
7038
7039 if (ok && !rscompat_auto_attack_3_1(compat, auto_perf,
7040 psize, protecor_flag)) {
7041 /* Upgrade failed */
7043 "\"%s\": %s: failed to upgrade.",
7044 filename, "auto_attack");
7045 ok = FALSE;
7046 }
7047
7048 if (psize) {
7049 FC_FREE(protecor_flag);
7050 }
7051 }
7052 }
7053 }
7054
7055 /* Section: actions */
7056 if (ok) {
7057 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
7058 int force_capture_units, force_bombard, force_explode_nuclear;
7059
7061 "actions.force_trade_route")) {
7062 /* Forbid entering the marketplace when a trade route can be
7063 * established. */
7064 BV_SET(action_by_number(ACTION_MARKETPLACE)->blocked_by,
7065 ACTION_TRADE_ROUTE);
7066 }
7067
7068 /* Forbid bombarding, exploading nuclear or attacking when it is
7069 * legal to capture units. */
7070 force_capture_units
7072 "actions.force_capture_units");
7073
7074 if (force_capture_units) {
7075 BV_SET(action_by_number(ACTION_BOMBARD)->blocked_by,
7076 ACTION_CAPTURE_UNITS);
7077 BV_SET(action_by_number(ACTION_BOMBARD2)->blocked_by,
7078 ACTION_CAPTURE_UNITS);
7079 BV_SET(action_by_number(ACTION_BOMBARD3)->blocked_by,
7080 ACTION_CAPTURE_UNITS);
7081 BV_SET(action_by_number(ACTION_NUKE)->blocked_by,
7082 ACTION_CAPTURE_UNITS);
7083 BV_SET(action_by_number(ACTION_NUKE_CITY)->blocked_by,
7084 ACTION_CAPTURE_UNITS);
7085 BV_SET(action_by_number(ACTION_NUKE_UNITS)->blocked_by,
7086 ACTION_CAPTURE_UNITS);
7087 BV_SET(action_by_number(ACTION_SUICIDE_ATTACK)->blocked_by,
7088 ACTION_CAPTURE_UNITS);
7089 BV_SET(action_by_number(ACTION_ATTACK)->blocked_by,
7090 ACTION_CAPTURE_UNITS);
7091 BV_SET(action_by_number(ACTION_CONQUER_CITY)->blocked_by,
7092 ACTION_CAPTURE_UNITS);
7093 BV_SET(action_by_number(ACTION_CONQUER_CITY2)->blocked_by,
7094 ACTION_CAPTURE_UNITS);
7095 BV_SET(action_by_number(ACTION_CONQUER_CITY3)->blocked_by,
7096 ACTION_CAPTURE_UNITS);
7097 BV_SET(action_by_number(ACTION_CONQUER_CITY4)->blocked_by,
7098 ACTION_CAPTURE_UNITS);
7099 }
7100
7101 /* Forbid exploding nuclear or attacking when it is legal to
7102 * bombard. */
7103 force_bombard
7105 "actions.force_bombard");
7106
7107 if (force_bombard) {
7108 BV_SET(action_by_number(ACTION_NUKE)->blocked_by,
7109 ACTION_BOMBARD);
7110 BV_SET(action_by_number(ACTION_NUKE_CITY)->blocked_by,
7111 ACTION_BOMBARD);
7112 BV_SET(action_by_number(ACTION_NUKE_UNITS)->blocked_by,
7113 ACTION_BOMBARD);
7114 BV_SET(action_by_number(ACTION_SUICIDE_ATTACK)->blocked_by,
7115 ACTION_BOMBARD);
7116 BV_SET(action_by_number(ACTION_ATTACK)->blocked_by,
7117 ACTION_BOMBARD);
7118 BV_SET(action_by_number(ACTION_CONQUER_CITY)->blocked_by,
7119 ACTION_BOMBARD);
7120 BV_SET(action_by_number(ACTION_CONQUER_CITY2)->blocked_by,
7121 ACTION_BOMBARD);
7122 BV_SET(action_by_number(ACTION_CONQUER_CITY3)->blocked_by,
7123 ACTION_BOMBARD);
7124 BV_SET(action_by_number(ACTION_CONQUER_CITY4)->blocked_by,
7125 ACTION_BOMBARD);
7126 BV_SET(action_by_number(ACTION_NUKE)->blocked_by,
7127 ACTION_BOMBARD2);
7128 BV_SET(action_by_number(ACTION_NUKE_CITY)->blocked_by,
7129 ACTION_BOMBARD2);
7130 BV_SET(action_by_number(ACTION_NUKE_UNITS)->blocked_by,
7131 ACTION_BOMBARD2);
7132 BV_SET(action_by_number(ACTION_SUICIDE_ATTACK)->blocked_by,
7133 ACTION_BOMBARD2);
7134 BV_SET(action_by_number(ACTION_ATTACK)->blocked_by,
7135 ACTION_BOMBARD2);
7136 BV_SET(action_by_number(ACTION_CONQUER_CITY)->blocked_by,
7137 ACTION_BOMBARD2);
7138 BV_SET(action_by_number(ACTION_CONQUER_CITY2)->blocked_by,
7139 ACTION_BOMBARD2);
7140 BV_SET(action_by_number(ACTION_CONQUER_CITY3)->blocked_by,
7141 ACTION_BOMBARD2);
7142 BV_SET(action_by_number(ACTION_CONQUER_CITY4)->blocked_by,
7143 ACTION_BOMBARD2);
7144 BV_SET(action_by_number(ACTION_NUKE)->blocked_by,
7145 ACTION_BOMBARD3);
7146 BV_SET(action_by_number(ACTION_NUKE_CITY)->blocked_by,
7147 ACTION_BOMBARD3);
7148 BV_SET(action_by_number(ACTION_NUKE_UNITS)->blocked_by,
7149 ACTION_BOMBARD3);
7150 BV_SET(action_by_number(ACTION_SUICIDE_ATTACK)->blocked_by,
7151 ACTION_BOMBARD3);
7152 BV_SET(action_by_number(ACTION_ATTACK)->blocked_by,
7153 ACTION_BOMBARD3);
7154 BV_SET(action_by_number(ACTION_CONQUER_CITY)->blocked_by,
7155 ACTION_BOMBARD3);
7156 BV_SET(action_by_number(ACTION_CONQUER_CITY2)->blocked_by,
7157 ACTION_BOMBARD3);
7158 BV_SET(action_by_number(ACTION_CONQUER_CITY3)->blocked_by,
7159 ACTION_BOMBARD3);
7160 BV_SET(action_by_number(ACTION_CONQUER_CITY4)->blocked_by,
7161 ACTION_BOMBARD3);
7162 }
7163
7164 /* Forbid attacking when it is legal to do explode nuclear. */
7165 force_explode_nuclear
7167 "actions.force_explode_nuclear");
7168
7169 if (force_explode_nuclear) {
7170 BV_SET(action_by_number(ACTION_SUICIDE_ATTACK)->blocked_by,
7171 ACTION_NUKE);
7172 BV_SET(action_by_number(ACTION_ATTACK)->blocked_by,
7173 ACTION_NUKE);
7174 BV_SET(action_by_number(ACTION_CONQUER_CITY)->blocked_by,
7175 ACTION_NUKE);
7176 BV_SET(action_by_number(ACTION_CONQUER_CITY2)->blocked_by,
7177 ACTION_NUKE);
7178 BV_SET(action_by_number(ACTION_CONQUER_CITY3)->blocked_by,
7179 ACTION_NUKE);
7180 BV_SET(action_by_number(ACTION_CONQUER_CITY4)->blocked_by,
7181 ACTION_NUKE);
7182 BV_SET(action_by_number(ACTION_SUICIDE_ATTACK)->blocked_by,
7183 ACTION_NUKE_CITY);
7184 BV_SET(action_by_number(ACTION_ATTACK)->blocked_by,
7185 ACTION_NUKE_CITY);
7186 BV_SET(action_by_number(ACTION_CONQUER_CITY)->blocked_by,
7187 ACTION_NUKE_CITY);
7188 BV_SET(action_by_number(ACTION_CONQUER_CITY2)->blocked_by,
7189 ACTION_NUKE_CITY);
7190 BV_SET(action_by_number(ACTION_CONQUER_CITY3)->blocked_by,
7191 ACTION_NUKE_CITY);
7192 BV_SET(action_by_number(ACTION_CONQUER_CITY4)->blocked_by,
7193 ACTION_NUKE_CITY);
7194 BV_SET(action_by_number(ACTION_SUICIDE_ATTACK)->blocked_by,
7195 ACTION_NUKE_UNITS);
7196 BV_SET(action_by_number(ACTION_ATTACK)->blocked_by,
7197 ACTION_NUKE_UNITS);
7198 BV_SET(action_by_number(ACTION_CONQUER_CITY)->blocked_by,
7199 ACTION_NUKE_UNITS);
7200 BV_SET(action_by_number(ACTION_CONQUER_CITY2)->blocked_by,
7201 ACTION_NUKE_UNITS);
7202 BV_SET(action_by_number(ACTION_CONQUER_CITY3)->blocked_by,
7203 ACTION_NUKE_UNITS);
7204 BV_SET(action_by_number(ACTION_CONQUER_CITY4)->blocked_by,
7205 ACTION_NUKE_UNITS);
7206 }
7207 }
7208
7209 action_iterate(act_id) {
7210 struct action *paction = action_by_number(act_id);
7211
7212 if (!load_action_blocked_by_list(file, filename, paction)) {
7213 ok = FALSE;
7214 break;
7215 }
7217
7218 if (ok && !lookup_bv_actions(file, filename,
7220 "actions.diplchance_initial_odds")) {
7221 ok = FALSE;
7222 }
7223
7224 if (ok) {
7225 /* If the "Poison City" action or the "Poison City Escape" action
7226 * should empty the granary. */
7227 /* TODO: empty granary and reduce population should become separate
7228 * action effect flags when actions are generalized. */
7232 "actions.poison_empties_food_stock");
7233
7234 /* If the "Steal Maps" action or the "Steal Maps Escape" action always
7235 * will reveal all cities when successful. */
7239 "actions.steal_maps_reveals_all_cities");
7240
7241 /* Allow setting certain properties for some actions before
7242 * generalized actions. */
7243 action_iterate(act_id) {
7244 if (!load_action_range(compat, file, act_id)) {
7245 ok = FALSE;
7246 } else if (!load_action_kind(file, act_id)) {
7247 ok = FALSE;
7248 } else if (!load_action_actor_consuming_always(file, act_id)) {
7249 ok = FALSE;
7250 } else {
7251 load_action_ui_name(file, act_id,
7254 }
7255
7256 if (!ok) {
7257 break;
7258 }
7260
7261 /* The quiet (don't auto generate help for) property of all actions
7262 * live in a single enum vector. This avoids generic action
7263 * expectations. */
7264 if (ok && secfile_entry_by_path(file, "actions.quiet_actions")) {
7265 enum gen_action *quiet_actions;
7266 size_t asize;
7267 int j;
7268
7269 quiet_actions =
7270 secfile_lookup_enum_vec(file, &asize, gen_action,
7271 "actions.quiet_actions");
7272
7273 if (!quiet_actions) {
7274 /* Entity exists but couldn't read it. */
7276 "\"%s\": actions.quiet_actions: bad action list",
7277 filename);
7278
7279 ok = FALSE;
7280 } else {
7281 for (j = 0; j < asize; j++) {
7282 /* Don't auto generate help text for this action. */
7283 action_by_number(quiet_actions[j])->quiet = TRUE;
7284 }
7285
7286 free(quiet_actions);
7287 }
7288 }
7289
7290 if (ok) {
7291 /* Hard code action sub results for now. */
7292
7293 /* Unit Enter Hut */
7294 action_by_result_iterate(paction, ACTRES_HUT_ENTER) {
7295 BV_SET(paction->sub_results, ACT_SUB_RES_HUT_ENTER);
7297 BV_SET(action_by_number(ACTION_PARADROP_ENTER)->sub_results,
7298 ACT_SUB_RES_HUT_ENTER);
7299 BV_SET(action_by_number(ACTION_PARADROP_ENTER_CONQUER)->sub_results,
7300 ACT_SUB_RES_HUT_ENTER);
7301
7302 /* Unit Frighten Hut */
7303 action_by_result_iterate(paction, ACTRES_HUT_FRIGHTEN) {
7304 BV_SET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN);
7306 BV_SET(action_by_number(ACTION_PARADROP_FRIGHTEN)->sub_results,
7307 ACT_SUB_RES_HUT_FRIGHTEN);
7308 BV_SET(action_by_number(ACTION_PARADROP_FRIGHTEN_CONQUER)->sub_results,
7309 ACT_SUB_RES_HUT_FRIGHTEN);
7310
7311 /* Unit May Embark */
7312 action_iterate(act_id) {
7313 struct action *paction = action_by_number(act_id);
7314
7316 "civstyle.paradrop_to_transport")
7317 && (action_has_result(paction, ACTRES_PARADROP)
7318 || action_has_result(paction, ACTRES_PARADROP_CONQUER))) {
7319 BV_SET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK);
7320 }
7321
7322 /* Embark actions will always embark, not maybe embark. */
7324 }
7325 }
7326 }
7327
7328 if (ok) {
7329 /* Forced actions after another action was successfully performed. */
7330
7331 /* "Bribe Unit" */
7332 if (!load_action_post_success_force(file, filename,
7335 ACTION_SPY_BRIBE_UNIT))) {
7336 ok = FALSE;
7337 } else if (!load_action_post_success_force(file, filename,
7340 ACTION_ATTACK))) {
7341 ok = FALSE;
7342 }
7343 }
7344
7345 if (ok) {
7346 struct action_auto_perf *auto_perf;
7347
7348 /* The city that made the unit's current tile native is gone.
7349 * Evaluated against an adjacent tile. */
7351 auto_perf->cause = AAPC_CITY_GONE;
7352
7353 /* I have no objections to moving this out of game's actions to
7354 * cities.ruleset, units.ruleset or an other location in game.ruleset
7355 * you find more suitable. -- Sveinung */
7356 if (!load_action_auto_actions(file, auto_perf,
7357 "actions.escape_city", filename)) {
7358 ok = FALSE;
7359 }
7360 }
7361
7362 if (ok) {
7363 struct action_auto_perf *auto_perf;
7364
7365 /* The unit's stack has been defeated and is scheduled for execution
7366 * but the unit has the CanEscape unit type flag.
7367 * Evaluated against an adjacent tile. */
7369 auto_perf->cause = AAPC_UNIT_STACK_DEATH;
7370
7371 /* I have no objections to moving this out of game's actions to
7372 * cities.ruleset, units.ruleset or an other location in game.ruleset
7373 * you find more suitable. -- Sveinung */
7374 if (!load_action_auto_actions(file, auto_perf,
7375 "actions.unit_stack_death", filename)) {
7376 ok = FALSE;
7377 }
7378 }
7379
7380 if (ok) {
7383
7384 if (sec) {
7385 section_list_iterate(sec, psection) {
7386 struct action_enabler *enabler;
7387 const char *sec_name = section_name(psection);
7388 struct action *paction;
7389 struct requirement_vector *actor_reqs;
7390 struct requirement_vector *target_reqs;
7391 const char *action_text;
7392
7393 enabler = action_enabler_new();
7394
7395 action_text = secfile_lookup_str(file, "%s.action", sec_name);
7396
7397 if (action_text == NULL) {
7399 "\"%s\" [%s] missing action to enable.",
7400 filename, sec_name);
7401 ok = FALSE;
7402 break;
7403 }
7404
7405 paction = action_by_rule_name(action_text);
7406 if (!paction) {
7408 "\"%s\" [%s] lists unknown action type \"%s\".",
7409 filename, sec_name, action_text);
7410 ok = FALSE;
7411 break;
7412 }
7413
7414 enabler->action = paction->id;
7415
7416 actor_reqs = lookup_req_list(file, compat, sec_name, "actor_reqs", action_text);
7417 if (actor_reqs == NULL) {
7418 ok = FALSE;
7419 break;
7420 }
7421
7422 requirement_vector_copy(&enabler->actor_reqs, actor_reqs);
7423
7424 target_reqs = lookup_req_list(file, compat, sec_name, "target_reqs", action_text);
7425 if (target_reqs == NULL) {
7426 ok = FALSE;
7427 break;
7428 }
7429
7430 requirement_vector_copy(&enabler->target_reqs, target_reqs);
7431
7432 action_enabler_add(enabler);
7434
7435 section_list_destroy(sec);
7436 }
7437 }
7438 }
7439
7440 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
7441 bool slow_invasions
7443 "global_unit_options.slow_invasions");
7444
7445 if (!rscompat_old_slow_invasions_3_1(compat, slow_invasions)) {
7446 ok = FALSE;
7447 }
7448 }
7449
7450 if (ok) {
7451 const char *tus_text;
7452 bool default_drbr = RS_DEFAULT_DAMAGE_REDUCES_BOMBARD_RATE;
7453
7454 /* section: combat_rules */
7457 "combat_rules.tired_attack");
7458
7461 "combat_rules.only_killing_makes_veteran");
7462
7465 "combat_rules.only_real_fight_makes_veteran");
7466
7469 "combat_rules.combat_odds_scaled_veterancy");
7470
7471 if (compat->compat_mode && compat->version < RSFORMAT_3_1) {
7472 /* Old hardcoded behavior was not to have bombard rate reduced for damage. */
7473 default_drbr = FALSE;
7474 }
7476 = secfile_lookup_bool_default(file, default_drbr,
7477 "combat_rules.damage_reduces_bombard_rate");
7478
7481 "combat_rules.low_firepower_badwallattacker");
7484 "combat_rules.low_firepower_pearl_harbour");
7487 "combat_rules.low_firepower_combat_bonus");
7490 "combat_rules.low_firepower_nonnat_bombard");
7491
7496 "combat_rules.nuke_pop_loss_pct");
7497
7502 "combat_rules.nuke_defender_survival_chance_pct");
7503
7504 /* section: borders */
7510 "borders.radius_sq_city");
7516 "borders.size_effect");
7517
7523 "borders.radius_sq_city_permanent");
7524
7525 /* section: research */
7527 "research.tech_cost_style");
7528 game.info.tech_cost_style = tech_cost_style_by_name(tus_text,
7530 if (!tech_cost_style_is_valid(game.info.tech_cost_style)) {
7532 "Unknown tech cost style \"%s\"",
7533 tus_text);
7534 ok = FALSE;
7535 }
7536
7538 "research.tech_leakage");
7539 game.info.tech_leakage = tech_leakage_style_by_name(tus_text,
7541 if (!tech_leakage_style_is_valid(game.info.tech_leakage)) {
7543 "Unknown tech leakage \"%s\"",
7544 tus_text);
7545 ok = FALSE;
7546 }
7547 if (game.info.tech_cost_style == TECH_COST_CIV1CIV2
7548 && game.info.tech_leakage != TECH_LEAKAGE_NONE) {
7549 log_error("Only tech_leakage \"%s\" supported with "
7550 "tech_cost_style \"%s\". ",
7551 tech_leakage_style_name(TECH_LEAKAGE_NONE),
7552 tech_cost_style_name(TECH_COST_CIV1CIV2));
7553 log_error("Switching to tech_leakage \"%s\".",
7554 tech_leakage_style_name(TECH_LEAKAGE_NONE));
7555 game.info.tech_leakage = TECH_LEAKAGE_NONE;
7556 }
7562 "research.base_tech_cost");
7563
7565 "research.tech_upkeep_style");
7566
7567 game.info.tech_upkeep_style = tech_upkeep_style_by_name(tus_text, fc_strcasecmp);
7568
7569 if (!tech_upkeep_style_is_valid(game.info.tech_upkeep_style)) {
7571 "Unknown tech upkeep style \"%s\"",
7572 tus_text);
7573 ok = FALSE;
7574 }
7575 }
7576
7577 if (ok) {
7583 "research.tech_upkeep_divider");
7584
7585 sval = secfile_lookup_str_default(file, NULL, "research.free_tech_method");
7586 if (sval == NULL) {
7588 "No free_tech_method given");
7589 ok = FALSE;
7590 } else {
7591 game.info.free_tech_method = free_tech_method_by_name(sval, fc_strcasecmp);
7592 if (!free_tech_method_is_valid(game.info.free_tech_method)) {
7594 "Bad value %s for free_tech_method.", sval);
7595 ok = FALSE;
7596 }
7597 }
7598 }
7599
7600 if (ok) {
7601 int cf;
7602
7603 /* section: culture */
7606 "culture.victory_min_points");
7609 "culture.victory_lead_pct");
7612 "culture.migration_pml");
7615 "culture.history_interest_pml");
7616
7617 /* section: calendar */
7620 "calendar.skip_year_0");
7623 "calendar.start_year");
7625 = secfile_lookup_int_default(file, 0, "calendar.fragments");
7626
7629 "Too many calendar fragments. Max is %d",
7631 ok = FALSE;
7633 }
7637 "calendar.positive_label"));
7641 "calendar.negative_label"));
7642
7643 for (cf = 0; cf < game.calendar.calendar_fragments; cf++) {
7644 const char *fname;
7645
7646 fname = secfile_lookup_str_default(file, NULL, "calendar.fragment_name%d", cf);
7647 if (fname != NULL) {
7648 strncpy(game.calendar.calendar_fragment_name[cf], fname,
7650 }
7651 }
7652 }
7653
7654 if (ok) {
7655 /* section playercolors */
7656 struct rgbcolor *prgbcolor = NULL;
7657 bool color_read = TRUE;
7658
7659 /* Check if the player list is defined and empty. */
7660 if (playercolor_count() != 0) {
7661 ok = FALSE;
7662 } else {
7663 i = 0;
7664
7665 while (color_read) {
7666 prgbcolor = NULL;
7667
7668 color_read = rgbcolor_load(file, &prgbcolor, "playercolors.colorlist%d", i);
7669 if (color_read) {
7670 playercolor_add(prgbcolor);
7671 }
7672
7673 i++;
7674 }
7675
7676 if (playercolor_count() == 0) {
7677 ruleset_error(NULL, LOG_ERROR, "No player colors defined!");
7678 ok = FALSE;
7679 }
7680
7681 if (ok) {
7682 fc_assert(game.plr_bg_color == NULL);
7683 if (!rgbcolor_load(file, &game.plr_bg_color, "playercolors.background")) {
7685 "No background player color defined! (%s)",
7686 secfile_error());
7687 ok = FALSE;
7688 }
7689 }
7690 }
7691 }
7692
7693 if (ok) {
7694 /* section: teams */
7695 svec = secfile_lookup_str_vec(file, &teams, "teams.names");
7696 if (team_slot_count() < teams) {
7697 teams = team_slot_count();
7698 }
7700 for (i = 0; i < teams; i++) {
7702 }
7703 free(svec);
7704
7706 nval = (NULL != sec ? section_list_size(sec) : 0);
7707 if (nval > MAX_DISASTER_TYPES) {
7708 int num = nval; /* No "size_t" to printf */
7709
7711 "\"%s\": Too many disaster types (%d, max %d)",
7712 filename, num, MAX_DISASTER_TYPES);
7713 section_list_destroy(sec);
7714 ok = FALSE;
7715 } else {
7717 }
7718 }
7719
7720 if (ok) {
7721 disaster_type_iterate(pdis) {
7722 int id = disaster_index(pdis);
7723 int j;
7724 size_t eff_count;
7725 struct requirement_vector *reqs;
7726 const char *sec_name = section_name(section_list_get(sec, id));
7727
7728 if (!ruleset_load_names(&pdis->name, NULL, file, sec_name)) {
7730 "\"%s\": Cannot load disaster names",
7731 filename);
7732 ok = FALSE;
7733 break;
7734 }
7735
7736 reqs = lookup_req_list(file, compat, sec_name, "reqs", disaster_rule_name(pdis));
7737 if (reqs == NULL) {
7738 ok = FALSE;
7739 break;
7740 }
7741 requirement_vector_copy(&pdis->reqs, reqs);
7742
7744 "%s.frequency", sec_name);
7745
7746 svec = secfile_lookup_str_vec(file, &eff_count, "%s.effects", sec_name);
7747
7748 BV_CLR_ALL(pdis->effects);
7749 for (j = 0; j < eff_count; j++) {
7750 const char *dsval = svec[j];
7751 enum disaster_effect_id effect;
7752
7753 effect = disaster_effect_id_by_name(dsval, fc_strcasecmp);
7754
7755 if (!disaster_effect_id_is_valid(effect)) {
7757 "\"%s\" disaster \"%s\": unknown effect \"%s\".",
7758 filename, disaster_rule_name(pdis), dsval);
7759 ok = FALSE;
7760 break;
7761 } else {
7762 BV_SET(pdis->effects, effect);
7763 }
7764 }
7765
7766 free(svec);
7767
7768 if (!ok) {
7769 break;
7770 }
7772 section_list_destroy(sec);
7773 }
7774
7775 if (ok) {
7777
7778 achievements_iterate(pach) {
7779 int id = achievement_index(pach);
7780 const char *sec_name = section_name(section_list_get(sec, id));
7781 const char *typename;
7782 const char *msg;
7783
7784 typename = secfile_lookup_str_default(file, NULL, "%s.type", sec_name);
7785
7786 pach->type = achievement_type_by_name(typename, fc_strcasecmp);
7787 if (!achievement_type_is_valid(pach->type)) {
7789 "Achievement has unknown type \"%s\".",
7790 typename != NULL ? typename : "(NULL)");
7791 ok = FALSE;
7792 }
7793
7794 if (ok) {
7796 "%s.unique", sec_name);
7797
7799 "%s.value", sec_name);
7800 pach->culture = secfile_lookup_int_default(file, 0,
7801 "%s.culture", sec_name);
7802
7803 msg = secfile_lookup_str_default(file, NULL, "%s.first_msg", sec_name);
7804 if (msg == NULL) {
7806 "Achievement %s has no first msg!", sec_name);
7807 ok = FALSE;
7808 } else {
7809 pach->first_msg = fc_strdup(msg);
7810 }
7811 }
7812
7813 if (ok) {
7814 msg = secfile_lookup_str_default(file, NULL, "%s.cons_msg", sec_name);
7815 if (msg == NULL) {
7816 if (!pach->unique) {
7818 "Achievement %s has no msg for consecutive gainers!",
7819 sec_name);
7820 ok = FALSE;
7821 }
7822 } else {
7823 pach->cons_msg = fc_strdup(msg);
7824 }
7825 }
7826
7827 if (!ok) {
7828 break;
7829 }
7831 section_list_destroy(sec);
7832 }
7833
7834 if (ok) {
7835 for (i = 0; (name = secfile_lookup_str_default(file, NULL,
7836 "trade.settings%d.type",
7837 i)); i++) {
7839
7840 if (type == TRT_LAST) {
7842 "\"%s\" unknown trade route type \"%s\".",
7843 filename, name);
7844 ok = FALSE;
7845 } else {
7847 const char *cancelling;
7848 const char *bonus;
7849
7850 set->trade_pct = secfile_lookup_int_default(file, 100,
7851 "trade.settings%d.pct", i);
7852 cancelling = secfile_lookup_str_default(file, "Active",
7853 "trade.settings%d.cancelling", i);
7855 if (set->cancelling == TRI_LAST) {
7857 "\"%s\" unknown trade route cancelling type \"%s\".",
7858 filename, cancelling);
7859 ok = FALSE;
7860 }
7861
7862 bonus = secfile_lookup_str_default(file, "None", "trade.settings%d.bonus", i);
7863
7864 set->bonus_type = trade_route_bonus_type_by_name(bonus, fc_strcasecmp);
7865
7866 if (!trade_route_bonus_type_is_valid(set->bonus_type)) {
7868 "\"%s\" unknown trade route bonus type \"%s\".",
7869 filename, bonus);
7870 ok = FALSE;
7871 }
7872 }
7873 }
7874 }
7875
7876 if (ok) {
7877 const char *str;
7878
7880 = secfile_lookup_int_default(file, 0, "trade.min_trade_route_val");
7881
7883 goods_selection_method_name(RS_DEFAULT_GOODS_SELECTION),
7884 "trade.goods_selection");
7885
7886 game.info.goods_selection = goods_selection_method_by_name(str, fc_strcasecmp);
7887
7888 if (!goods_selection_method_is_valid(game.info.goods_selection)) {
7890 "\"%s\" goods selection method \"%s\" unknown.",
7891 filename, str);
7892 ok = FALSE;
7893 }
7894 }
7895
7896 if (ok) {
7898
7899 goods_type_iterate(pgood) {
7900 int id = goods_index(pgood);
7901 const char *sec_name = section_name(section_list_get(sec, id));
7902 struct requirement_vector *reqs;
7903 const char **slist;
7904 int j;
7905
7906 reqs = lookup_req_list(file, compat, sec_name, "reqs", goods_rule_name(pgood));
7907 if (reqs == NULL) {
7908 ok = FALSE;
7909 break;
7910 }
7911 requirement_vector_copy(&pgood->reqs, reqs);
7912
7913 pgood->from_pct = secfile_lookup_int_default(file, 100,
7914 "%s.from_pct", sec_name);
7915 pgood->to_pct = secfile_lookup_int_default(file, 100,
7916 "%s.to_pct", sec_name);
7917 pgood->onetime_pct = secfile_lookup_int_default(file, 100,
7918 "%s.onetime_pct", sec_name);
7919
7920 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
7921 BV_CLR_ALL(pgood->flags);
7922 for (j = 0; j < nval; j++) {
7923 enum goods_flag_id flag;
7924
7925 sval = slist[j];
7926 flag = goods_flag_id_by_name(sval, fc_strcasecmp);
7927 if (!goods_flag_id_is_valid(flag)) {
7928 ruleset_error(NULL, LOG_ERROR, "\"%s\" good \"%s\": unknown flag \"%s\".",
7929 filename, goods_rule_name(pgood), sval);
7930 ok = FALSE;
7931 break;
7932 } else {
7933 BV_SET(pgood->flags, flag);
7934 }
7935 }
7936 free(slist);
7937
7938 pgood->helptext = lookup_strvec(file, sec_name, "helptext");
7940 section_list_destroy(sec);
7941 }
7942
7943 if (ok) {
7945
7946 if (sec != NULL) {
7947 int num = section_list_size(sec);
7948
7949 for (i = 0; i < num; i++) {
7950 const char *sec_name = section_name(section_list_get(sec, i));
7951 const char *clause_name = secfile_lookup_str_default(file, NULL,
7952 "%s.type", sec_name);
7953 enum clause_type type = clause_type_by_name(clause_name, fc_strcasecmp);
7954 struct clause_info *info;
7955 struct requirement_vector *reqs;
7956
7957 if (!clause_type_is_valid(type)) {
7959 "\"%s\" unknown clause type \"%s\".",
7960 filename, clause_name);
7961 ok = FALSE;
7962 break;
7963 }
7964
7965 info = clause_info_get(type);
7966
7967 if (info->enabled) {
7969 "\"%s\" dublicate clause type \"%s\" definition.",
7970 filename, clause_name);
7971 ok = FALSE;
7972 break;
7973 }
7974
7975 reqs = lookup_req_list(file, compat, sec_name, "giver_reqs", clause_name);
7976 if (reqs == NULL) {
7977 ok = FALSE;
7978 break;
7979 }
7980 requirement_vector_copy(&info->giver_reqs, reqs);
7981
7982 reqs = lookup_req_list(file, compat, sec_name, "receiver_reqs", clause_name);
7983 if (reqs == NULL) {
7984 ok = FALSE;
7985 break;
7986 }
7987 requirement_vector_copy(&info->receiver_reqs, reqs);
7988
7989 info->enabled = TRUE;
7990 }
7991 }
7992 section_list_destroy(sec);
7993 }
7994
7995 /* secfile_check_unused() is not here, but only after also settings section
7996 * has been loaded. */
7997
7998 return ok;
7999}
8000
8001/**********************************************************************/
8005static void send_ruleset_unit_classes(struct conn_list *dest)
8006{
8007 struct packet_ruleset_unit_class packet;
8008 struct packet_ruleset_unit_class_flag fpacket;
8009 int i;
8010
8011 for (i = 0; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
8012 const char *flagname;
8013 const char *helptxt;
8014
8015 fpacket.id = i + UCF_USER_FLAG_1;
8016
8017 flagname = unit_class_flag_id_name(i + UCF_USER_FLAG_1);
8018 if (flagname == NULL) {
8019 fpacket.name[0] = '\0';
8020 } else {
8021 sz_strlcpy(fpacket.name, flagname);
8022 }
8023
8024 helptxt = unit_class_flag_helptxt(i + UCF_USER_FLAG_1);
8025 if (helptxt == NULL) {
8026 fpacket.helptxt[0] = '\0';
8027 } else {
8028 sz_strlcpy(fpacket.helptxt, helptxt);
8029 }
8030
8032 }
8033
8035 packet.id = uclass_number(c);
8036 sz_strlcpy(packet.name, untranslated_name(&c->name));
8037 sz_strlcpy(packet.rule_name, rule_name_get(&c->name));
8038 packet.min_speed = c->min_speed;
8039 packet.hp_loss_pct = c->hp_loss_pct;
8040 packet.non_native_def_pct = c->non_native_def_pct;
8041 packet.flags = c->flags;
8042
8043 PACKET_STRVEC_COMPUTE(packet.helptext, c->helptext);
8044
8045 lsend_packet_ruleset_unit_class(dest, &packet);
8047}
8048
8049/**********************************************************************/
8053static void send_ruleset_units(struct conn_list *dest)
8054{
8055 struct packet_ruleset_unit packet;
8056#ifdef FREECIV_WEB
8057 struct packet_web_ruleset_unit_addition web_packet;
8058#endif /* FREECIV_WEB */
8059 struct packet_ruleset_unit_flag fpacket;
8060 int i;
8061
8062 for (i = 0; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
8063 const char *flagname;
8064 const char *helptxt;
8065
8066 fpacket.id = i + UTYF_USER_FLAG_1;
8067
8068 flagname = unit_type_flag_id_name(i + UTYF_USER_FLAG_1);
8069 if (flagname == NULL) {
8070 fpacket.name[0] = '\0';
8071 } else {
8072 sz_strlcpy(fpacket.name, flagname);
8073 }
8074
8075 helptxt = unit_type_flag_helptxt(i + UTYF_USER_FLAG_1);
8076 if (helptxt == NULL) {
8077 fpacket.helptxt[0] = '\0';
8078 } else {
8079 sz_strlcpy(fpacket.helptxt, helptxt);
8080 }
8081
8082 lsend_packet_ruleset_unit_flag(dest, &fpacket);
8083 }
8084
8086 packet.id = utype_number(u);
8087 sz_strlcpy(packet.name, untranslated_name(&u->name));
8088 sz_strlcpy(packet.rule_name, rule_name_get(&u->name));
8089 sz_strlcpy(packet.sound_move, u->sound_move);
8090 sz_strlcpy(packet.sound_move_alt, u->sound_move_alt);
8091 sz_strlcpy(packet.sound_fight, u->sound_fight);
8092 sz_strlcpy(packet.sound_fight_alt, u->sound_fight_alt);
8093 sz_strlcpy(packet.graphic_str, u->graphic_str);
8094 sz_strlcpy(packet.graphic_alt, u->graphic_alt);
8096 packet.build_cost = u->build_cost;
8097 packet.pop_cost = u->pop_cost;
8098 packet.attack_strength = u->attack_strength;
8099 packet.defense_strength = u->defense_strength;
8100 packet.move_rate = u->move_rate;
8101 packet.tech_requirement = u->require_advance
8102 ? advance_number(u->require_advance)
8103 : advance_count();
8104
8105 i = 0;
8106 requirement_vector_iterate(&u->build_reqs, req) {
8107 packet.build_reqs[i++] = *req;
8109 packet.build_reqs_count = i;
8110
8111 packet.vision_radius_sq = u->vision_radius_sq;
8112 packet.transport_capacity = u->transport_capacity;
8113 packet.hp = u->hp;
8114 packet.firepower = u->firepower;
8115 packet.obsoleted_by = u->obsoleted_by
8116 ? utype_number(u->obsoleted_by)
8117 : utype_count();
8118 packet.converted_to = u->converted_to
8119 ? utype_number(u->converted_to)
8120 : utype_count();
8121 packet.convert_time = u->convert_time;
8122 packet.fuel = u->fuel;
8123 packet.flags = u->flags;
8124 packet.roles = u->roles;
8125 packet.happy_cost = u->happy_cost;
8127 packet.upkeep[o] = u->upkeep[o];
8129 packet.paratroopers_range = u->paratroopers_range;
8130 packet.bombard_rate = u->bombard_rate;
8131 packet.city_size = u->city_size;
8132 packet.city_slots = u->city_slots;
8133 packet.tp_defense = u->tp_defense;
8134 packet.cargo = u->cargo;
8135 packet.targets = u->targets;
8136 packet.embarks = u->embarks;
8137 packet.disembarks = u->disembarks;
8138 packet.vlayer = u->vlayer;
8139
8140 if (u->veteran == NULL) {
8141 /* Use the default veteran system. */
8142 packet.veteran_levels = 0;
8143 } else {
8144 /* Per unit veteran system definition. */
8146
8147 for (i = 0; i < packet.veteran_levels; i++) {
8148 const struct veteran_level *vlevel = utype_veteran_level(u, i);
8149
8150 sz_strlcpy(packet.veteran_name[i], untranslated_name(&vlevel->name));
8151 packet.power_fact[i] = vlevel->power_fact;
8152 packet.move_bonus[i] = vlevel->move_bonus;
8153 packet.base_raise_chance[i] = vlevel->base_raise_chance;
8154 packet.work_raise_chance[i] = vlevel->work_raise_chance;
8155 }
8156 }
8157 PACKET_STRVEC_COMPUTE(packet.helptext, u->helptext);
8158
8159 packet.worker = u->adv.worker;
8160
8161#ifdef FREECIV_WEB
8162 web_packet.id = utype_number(u);
8163
8164 BV_CLR_ALL(web_packet.utype_actions);
8165
8166 action_iterate(act) {
8167 if (utype_can_do_action(u, act)) {
8168 BV_SET(web_packet.utype_actions, act);
8169 }
8171#endif /* FREECIV_WEB */
8172
8173 lsend_packet_ruleset_unit(dest, &packet);
8174 web_lsend_packet(ruleset_unit_addition, dest, &web_packet);
8175
8176 combat_bonus_list_iterate(u->bonuses, pbonus) {
8177 struct packet_ruleset_unit_bonus bonuspacket;
8178
8179 bonuspacket.unit = packet.id;
8180 bonuspacket.flag = pbonus->flag;
8181 bonuspacket.type = pbonus->type;
8182 bonuspacket.value = pbonus->value;
8183 bonuspacket.quiet = pbonus->quiet;
8184
8185 lsend_packet_ruleset_unit_bonus(dest, &bonuspacket);
8188}
8189
8190/**********************************************************************/
8194static void send_ruleset_specialists(struct conn_list *dest)
8195{
8196 struct packet_ruleset_specialist packet;
8197
8198 specialist_type_iterate(spec_id) {
8199 struct specialist *s = specialist_by_number(spec_id);
8200 int j;
8201
8202 packet.id = spec_id;
8204 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
8208 j = 0;
8209 requirement_vector_iterate(&s->reqs, preq) {
8210 packet.reqs[j++] = *preq;
8212 packet.reqs_count = j;
8213
8215
8216 lsend_packet_ruleset_specialist(dest, &packet);
8218}
8219/**********************************************************************/
8222static void send_ruleset_tech_classes(struct conn_list *dest)
8223{
8224 struct packet_ruleset_tech_class packet;
8225
8226 tech_class_iterate(ptclass) {
8227 packet.id = ptclass->idx;
8228 sz_strlcpy(packet.name, untranslated_name(&ptclass->name));
8229 sz_strlcpy(packet.rule_name, rule_name_get(&ptclass->name));
8230 packet.cost_pct = ptclass->cost_pct;
8231
8232 lsend_packet_ruleset_tech_class(dest, &packet);
8234}
8235
8236/**********************************************************************/
8240static void send_ruleset_techs(struct conn_list *dest)
8241{
8242 struct packet_ruleset_tech packet;
8243 struct packet_ruleset_tech_flag fpacket;
8244 int i;
8245
8246 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
8247 const char *flagname;
8248 const char *helptxt;
8249
8250 fpacket.id = i + TECH_USER_1;
8251
8252 flagname = tech_flag_id_name_cb(i + TECH_USER_1);
8253 if (flagname == NULL) {
8254 fpacket.name[0] = '\0';
8255 } else {
8256 sz_strlcpy(fpacket.name, flagname);
8257 }
8258
8259 helptxt = tech_flag_helptxt(i + TECH_USER_1);
8260 if (helptxt == NULL) {
8261 fpacket.helptxt[0] = '\0';
8262 } else {
8263 sz_strlcpy(fpacket.helptxt, helptxt);
8264 }
8265
8266 lsend_packet_ruleset_tech_flag(dest, &fpacket);
8267 }
8268
8270 packet.id = advance_number(a);
8271 packet.removed = !valid_advance(a);
8272 if (a->tclass == NULL) {
8273 packet.tclass = 0;
8274 } else {
8275 packet.tclass = a->tclass->idx;
8276 }
8277 sz_strlcpy(packet.name, untranslated_name(&a->name));
8278 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8279 sz_strlcpy(packet.graphic_str, a->graphic_str);
8280 sz_strlcpy(packet.graphic_alt, a->graphic_alt);
8281
8282 /* Current size of the packet's research_reqs requirement vector. */
8283 i = 0;
8284
8285 /* The requirements req1 and req2 are needed to research a tech. Send
8286 * them in the research_reqs requirement vector. Range is set to player
8287 * since pooled research is configurable. */
8288
8289 if ((a->require[AR_ONE] != A_NEVER)
8290 && advance_number(a->require[AR_ONE]) > A_NONE) {
8291 packet.research_reqs[i++]
8292 = req_from_values(VUT_ADVANCE, REQ_RANGE_PLAYER,
8293 FALSE, TRUE, FALSE,
8294 advance_number(a->require[AR_ONE]));
8295 }
8296
8297 if ((a->require[AR_TWO] != A_NEVER)
8298 && advance_number(a->require[AR_TWO]) > A_NONE) {
8299 packet.research_reqs[i++]
8300 = req_from_values(VUT_ADVANCE, REQ_RANGE_PLAYER,
8301 FALSE, TRUE, FALSE,
8302 advance_number(a->require[AR_TWO]));;
8303 }
8304
8305 /* The requirements of the tech's research_reqs also goes in the
8306 * packet's research_reqs requirement vector. */
8307 requirement_vector_iterate(&a->research_reqs, req) {
8308 packet.research_reqs[i++] = *req;
8310
8311 /* The packet's research_reqs should contain req1, req2 and the
8312 * requirements of the tech's research_reqs. */
8313 packet.research_reqs_count = i;
8314
8315 packet.root_req = a->require[AR_ROOT]
8316 ? advance_number(a->require[AR_ROOT])
8317 : advance_count();
8318
8319 packet.flags = a->flags;
8320 packet.cost = a->cost;
8321 packet.num_reqs = a->num_reqs;
8322 PACKET_STRVEC_COMPUTE(packet.helptext, a->helptext);
8323
8324 lsend_packet_ruleset_tech(dest, &packet);
8326}
8327
8328/**********************************************************************/
8332static void send_ruleset_buildings(struct conn_list *dest)
8333{
8335 struct packet_ruleset_building packet;
8336 int j;
8337
8338 packet.id = improvement_number(b);
8339 packet.genus = b->genus;
8340 sz_strlcpy(packet.name, untranslated_name(&b->name));
8341 sz_strlcpy(packet.rule_name, rule_name_get(&b->name));
8342 sz_strlcpy(packet.graphic_str, b->graphic_str);
8343 sz_strlcpy(packet.graphic_alt, b->graphic_alt);
8344 j = 0;
8345 requirement_vector_iterate(&b->reqs, preq) {
8346 packet.reqs[j++] = *preq;
8348 packet.reqs_count = j;
8349 j = 0;
8350 requirement_vector_iterate(&b->obsolete_by, pobs) {
8351 packet.obs_reqs[j++] = *pobs;
8353 packet.obs_count = j;
8354 packet.build_cost = b->build_cost;
8355 packet.upkeep = b->upkeep;
8356 packet.sabotage = b->sabotage;
8357 packet.flags = b->flags;
8358 sz_strlcpy(packet.soundtag, b->soundtag);
8359 sz_strlcpy(packet.soundtag_alt, b->soundtag_alt);
8360 PACKET_STRVEC_COMPUTE(packet.helptext, b->helptext);
8361
8362 lsend_packet_ruleset_building(dest, &packet);
8364}
8365
8366/**********************************************************************/
8370static void send_ruleset_terrain(struct conn_list *dest)
8371{
8372 struct packet_ruleset_terrain packet;
8373 struct packet_ruleset_terrain_flag fpacket;
8374 int i;
8375
8377
8378 for (i = 0; i < MAX_NUM_USER_TER_FLAGS; i++) {
8379 const char *flagname;
8380 const char *helptxt;
8381
8382 fpacket.id = i + TER_USER_1;
8383
8384 flagname = terrain_flag_id_name_cb(i + TER_USER_1);
8385 if (flagname == NULL) {
8386 fpacket.name[0] = '\0';
8387 } else {
8388 sz_strlcpy(fpacket.name, flagname);
8389 }
8390
8391 helptxt = terrain_flag_helptxt(i + TER_USER_1);
8392 if (helptxt == NULL) {
8393 fpacket.helptxt[0] = '\0';
8394 } else {
8395 sz_strlcpy(fpacket.helptxt, helptxt);
8396 }
8397
8398 lsend_packet_ruleset_terrain_flag(dest, &fpacket);
8399 }
8400
8401 terrain_type_iterate(pterrain) {
8402 struct extra_type **r;
8403
8404 packet.id = terrain_number(pterrain);
8405 packet.tclass = pterrain->tclass;
8406 packet.native_to = pterrain->native_to;
8407
8408 sz_strlcpy(packet.name, untranslated_name(&pterrain->name));
8409 sz_strlcpy(packet.rule_name, rule_name_get(&pterrain->name));
8410 sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
8411 sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
8412
8413 packet.movement_cost = pterrain->movement_cost;
8414 packet.defense_bonus = pterrain->defense_bonus;
8415
8417 packet.output[o] = pterrain->output[o];
8419
8420 packet.num_resources = 0;
8421 for (r = pterrain->resources; *r; r++) {
8422 packet.resources[packet.num_resources++] = extra_number(*r);
8423 }
8424
8426 packet.road_output_incr_pct[o] = pterrain->road_output_incr_pct[o];
8428
8429 packet.base_time = pterrain->base_time;
8430 packet.road_time = pterrain->road_time;
8431
8432 packet.cultivate_result = (pterrain->cultivate_result
8433 ? terrain_number(pterrain->cultivate_result)
8434 : terrain_count());
8435 packet.cultivate_time = pterrain->cultivate_time;
8436
8437 packet.plant_result = (pterrain->plant_result
8438 ? terrain_number(pterrain->plant_result)
8439 : terrain_count());
8440 packet.plant_time = pterrain->plant_time;
8441
8442 packet.irrigation_food_incr = pterrain->irrigation_food_incr;
8443 packet.irrigation_time = pterrain->irrigation_time;
8444
8445 packet.mining_shield_incr = pterrain->mining_shield_incr;
8446 packet.mining_time = pterrain->mining_time;
8447
8448 packet.animal = (pterrain->animal == NULL ? -1 : utype_number(pterrain->animal));
8449 packet.transform_result = (pterrain->transform_result
8450 ? terrain_number(pterrain->transform_result)
8451 : terrain_count());
8452 packet.placing_time = pterrain->placing_time;
8453 packet.pillage_time = pterrain->pillage_time;
8454 packet.transform_time = pterrain->transform_time;
8455 packet.clean_pollution_time = pterrain->clean_pollution_time;
8456 packet.clean_fallout_time = pterrain->clean_fallout_time;
8457
8458 packet.flags = pterrain->flags;
8459
8460 packet.color_red = pterrain->rgb->r;
8461 packet.color_green = pterrain->rgb->g;
8462 packet.color_blue = pterrain->rgb->b;
8463
8464 PACKET_STRVEC_COMPUTE(packet.helptext, pterrain->helptext);
8465
8466 lsend_packet_ruleset_terrain(dest, &packet);
8468}
8469
8470/**********************************************************************/
8473static void send_ruleset_resources(struct conn_list *dest)
8474{
8475 struct packet_ruleset_resource packet;
8476
8477 extra_type_by_cause_iterate(EC_RESOURCE, presource) {
8478 packet.id = extra_index(presource);
8479
8481 packet.output[o] = presource->data.resource->output[o];
8483
8484 lsend_packet_ruleset_resource(dest, &packet);
8486}
8487
8488/**********************************************************************/
8492static void send_ruleset_extras(struct conn_list *dest)
8493{
8494 struct packet_ruleset_extra packet;
8495 struct packet_ruleset_extra_flag fpacket;
8496 int i;
8497
8498 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
8499 const char *flagname;
8500 const char *helptxt;
8501
8502 fpacket.id = i + EF_USER_FLAG_1;
8503
8504 flagname = extra_flag_id_name(i + EF_USER_FLAG_1);
8505 if (flagname == NULL) {
8506 fpacket.name[0] = '\0';
8507 } else {
8508 sz_strlcpy(fpacket.name, flagname);
8509 }
8510
8511 helptxt = extra_flag_helptxt(i + EF_USER_FLAG_1);
8512 if (helptxt == NULL) {
8513 fpacket.helptxt[0] = '\0';
8514 } else {
8515 sz_strlcpy(fpacket.helptxt, helptxt);
8516 }
8517
8518 lsend_packet_ruleset_extra_flag(dest, &fpacket);
8519 }
8520
8522 int j;
8523
8524 packet.id = extra_number(e);
8525 sz_strlcpy(packet.name, untranslated_name(&e->name));
8526 sz_strlcpy(packet.rule_name, rule_name_get(&e->name));
8527
8528 packet.category = e->category;
8529
8530 BV_CLR_ALL(packet.causes);
8531 for (j = 0; j < EC_COUNT; j++) {
8532 if (is_extra_caused_by(e, j)) {
8533 BV_SET(packet.causes, j);
8534 }
8535 }
8536
8537 BV_CLR_ALL(packet.rmcauses);
8538 for (j = 0; j < ERM_COUNT; j++) {
8539 if (is_extra_removed_by(e, j)) {
8540 BV_SET(packet.rmcauses, j);
8541 }
8542 }
8543
8544 sz_strlcpy(packet.activity_gfx, e->activity_gfx);
8545 sz_strlcpy(packet.act_gfx_alt, e->act_gfx_alt);
8546 sz_strlcpy(packet.act_gfx_alt2, e->act_gfx_alt2);
8547 sz_strlcpy(packet.rmact_gfx, e->rmact_gfx);
8548 sz_strlcpy(packet.rmact_gfx_alt, e->rmact_gfx_alt);
8549 sz_strlcpy(packet.graphic_str, e->graphic_str);
8550 sz_strlcpy(packet.graphic_alt, e->graphic_alt);
8551
8552 j = 0;
8553 requirement_vector_iterate(&e->reqs, preq) {
8554 packet.reqs[j++] = *preq;
8556 packet.reqs_count = j;
8557
8558 j = 0;
8559 requirement_vector_iterate(&e->rmreqs, preq) {
8560 packet.rmreqs[j++] = *preq;
8562 packet.rmreqs_count = j;
8563
8564 packet.appearance_chance = e->appearance_chance;
8565 j = 0;
8566 requirement_vector_iterate(&e->appearance_reqs, preq) {
8567 packet.appearance_reqs[j++] = *preq;
8569 packet.appearance_reqs_count = j;
8570
8571 packet.disappearance_chance = e->disappearance_chance;
8572 j = 0;
8573 requirement_vector_iterate(&e->disappearance_reqs, preq) {
8574 packet.disappearance_reqs[j++] = *preq;
8576 packet.disappearance_reqs_count = j;
8577
8578 packet.visibility_req = e->visibility_req;
8579 packet.buildable = e->buildable;
8580 packet.generated = e->generated;
8581 packet.build_time = e->build_time;
8582 packet.build_time_factor = e->build_time_factor;
8583 packet.removal_time = e->removal_time;
8584 packet.removal_time_factor = e->removal_time_factor;
8585 packet.infracost = e->infracost;
8586 packet.defense_bonus = e->defense_bonus;
8587 packet.eus = e->eus;
8588
8589 packet.native_to = e->native_to;
8590
8591 packet.flags = e->flags;
8592 packet.hidden_by = e->hidden_by;
8593 packet.bridged_over = e->bridged_over;
8594 packet.conflicts = e->conflicts;
8595
8596 PACKET_STRVEC_COMPUTE(packet.helptext, e->helptext);
8597
8598 lsend_packet_ruleset_extra(dest, &packet);
8600}
8601
8602/**********************************************************************/
8606static void send_ruleset_bases(struct conn_list *dest)
8607{
8608 extra_type_by_cause_iterate(EC_BASE, pextra) {
8609 struct base_type *b = extra_base_get(pextra);
8610 struct packet_ruleset_base packet;
8611
8612 packet.id = base_number(b);
8613
8614 packet.gui_type = b->gui_type;
8615 packet.border_sq = b->border_sq;
8616 packet.vision_main_sq = b->vision_main_sq;
8617 packet.vision_invis_sq = b->vision_invis_sq;
8618 packet.vision_subs_sq = b->vision_subs_sq;
8619
8620 lsend_packet_ruleset_base(dest, &packet);
8622}
8623
8624/**********************************************************************/
8628static void send_ruleset_roads(struct conn_list *dest)
8629{
8630 struct packet_ruleset_road packet;
8631
8632 extra_type_by_cause_iterate(EC_ROAD, pextra) {
8633 struct road_type *r = extra_road_get(pextra);
8634 int j;
8635
8636 packet.id = road_number(r);
8637
8638 packet.gui_type = r->gui_type;
8639
8640 j = 0;
8642 packet.first_reqs[j++] = *preq;
8644 packet.first_reqs_count = j;
8645
8646 packet.move_cost = r->move_cost;
8647 packet.move_mode = r->move_mode;
8648
8650 packet.tile_incr_const[o] = r->tile_incr_const[o];
8651 packet.tile_incr[o] = r->tile_incr[o];
8652 packet.tile_bonus[o] = r->tile_bonus[o];
8654
8655 packet.compat = r->compat;
8656
8657 packet.integrates = r->integrates;
8658 packet.flags = r->flags;
8659
8660 lsend_packet_ruleset_road(dest, &packet);
8662}
8663
8664/**********************************************************************/
8668static void send_ruleset_goods(struct conn_list *dest)
8669{
8670 struct packet_ruleset_goods packet;
8671
8673 int j;
8674
8675 packet.id = goods_number(g);
8676 sz_strlcpy(packet.name, untranslated_name(&g->name));
8677 sz_strlcpy(packet.rule_name, rule_name_get(&g->name));
8678
8679 j = 0;
8680 requirement_vector_iterate(&g->reqs, preq) {
8681 packet.reqs[j++] = *preq;
8683 packet.reqs_count = j;
8684
8685 packet.from_pct = g->from_pct;
8686 packet.to_pct = g->to_pct;
8687 packet.onetime_pct = g->onetime_pct;
8688 packet.flags = g->flags;
8689
8690 PACKET_STRVEC_COMPUTE(packet.helptext, g->helptext);
8691
8692 lsend_packet_ruleset_goods(dest, &packet);
8694}
8695
8696/**********************************************************************/
8700static void send_ruleset_disasters(struct conn_list *dest)
8701{
8702 struct packet_ruleset_disaster packet;
8703
8705 int j;
8706
8707 packet.id = disaster_number(d);
8708
8709 sz_strlcpy(packet.name, untranslated_name(&d->name));
8710 sz_strlcpy(packet.rule_name, rule_name_get(&d->name));
8711
8712 j = 0;
8713 requirement_vector_iterate(&d->reqs, preq) {
8714 packet.reqs[j++] = *preq;
8716 packet.reqs_count = j;
8717
8718 packet.frequency = d->frequency;
8719
8720 packet.effects = d->effects;
8721
8722 lsend_packet_ruleset_disaster(dest, &packet);
8724}
8725
8726/**********************************************************************/
8730static void send_ruleset_achievements(struct conn_list *dest)
8731{
8732 struct packet_ruleset_achievement packet;
8733
8735 packet.id = achievement_number(a);
8736
8737 sz_strlcpy(packet.name, untranslated_name(&a->name));
8738 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8739
8740 packet.type = a->type;
8741 packet.unique = a->unique;
8742 packet.value = a->value;
8743
8744 lsend_packet_ruleset_achievement(dest, &packet);
8746}
8747
8748/**********************************************************************/
8751static void send_ruleset_actions(struct conn_list *dest)
8752{
8753 struct packet_ruleset_action packet;
8754
8755 action_iterate(act) {
8756 struct action *paction = action_by_number(act);
8757
8758 packet.id = act;
8760 packet.quiet = action_by_number(act)->quiet;
8761
8762 packet.result = paction->result;
8763 packet.sub_results = paction->sub_results;
8765
8766 packet.act_kind = action_by_number(act)->actor_kind;
8767 packet.tgt_kind = action_by_number(act)->target_kind;
8769
8772 packet.blocked_by = action_by_number(act)->blocked_by;
8773
8774 lsend_packet_ruleset_action(dest, &packet);
8776}
8777
8778/**********************************************************************/
8781static void send_ruleset_action_enablers(struct conn_list *dest)
8782{
8783 int counter;
8784 struct packet_ruleset_action_enabler packet;
8785
8786 action_enablers_iterate(enabler) {
8787 packet.enabled_action = enabler->action;
8788
8789 counter = 0;
8790 requirement_vector_iterate(&enabler->actor_reqs, req) {
8791 packet.actor_reqs[counter++] = *req;
8793 packet.actor_reqs_count = counter;
8794
8795 counter = 0;
8796 requirement_vector_iterate(&enabler->target_reqs, req) {
8797 packet.target_reqs[counter++] = *req;
8799 packet.target_reqs_count = counter;
8800
8803}
8804
8805/**********************************************************************/
8809static void send_ruleset_action_auto_performers(struct conn_list *dest)
8810{
8811 int counter;
8812 int id;
8813 struct packet_ruleset_action_auto packet;
8814
8815 id = 0;
8817 packet.id = id++;
8818
8819 packet.cause = aperf->cause;
8820
8821 counter = 0;
8822 requirement_vector_iterate(&aperf->reqs, req) {
8823 packet.reqs[counter++] = *req;
8825 packet.reqs_count = counter;
8826
8827 for (counter = 0;
8828 /* Can't list more actions than all actions. */
8829 counter < NUM_ACTIONS
8830 /* ACTION_NONE terminates the list. */
8831 && aperf->alternatives[counter] != ACTION_NONE;
8832 counter++) {
8833 packet.alternatives[counter] = aperf->alternatives[counter];
8834 }
8835 packet.alternatives_count = counter;
8836
8837 lsend_packet_ruleset_action_auto(dest, &packet);
8839}
8840
8841/**********************************************************************/
8845static void send_ruleset_trade_routes(struct conn_list *dest)
8846{
8847 struct packet_ruleset_trade packet;
8849
8850 for (type = TRT_NATIONAL; type < TRT_LAST; type++) {
8852
8853 packet.id = type;
8854 packet.trade_pct = set->trade_pct;
8855 packet.cancelling = set->cancelling;
8856 packet.bonus_type = set->bonus_type;
8857
8858 lsend_packet_ruleset_trade(dest, &packet);
8859 }
8860}
8861
8862/**********************************************************************/
8866static void send_ruleset_governments(struct conn_list *dest)
8867{
8868 struct packet_ruleset_government gov;
8870 int j;
8871
8873 /* send one packet_government */
8874 gov.id = government_number(g);
8875
8876 j = 0;
8877 requirement_vector_iterate(&g->reqs, preq) {
8878 gov.reqs[j++] = *preq;
8880 gov.reqs_count = j;
8881
8882 sz_strlcpy(gov.name, untranslated_name(&g->name));
8883 sz_strlcpy(gov.rule_name, rule_name_get(&g->name));
8884 sz_strlcpy(gov.graphic_str, g->graphic_str);
8885 sz_strlcpy(gov.graphic_alt, g->graphic_alt);
8886 PACKET_STRVEC_COMPUTE(gov.helptext, g->helptext);
8887
8889
8890 /* Send one packet_government_ruler_title per ruler title. */
8892 const struct nation_type *pnation = ruler_title_nation(pruler_title);
8893
8894 title.gov = government_number(g);
8895 title.nation = pnation ? nation_number(pnation) : nation_count();
8896 sz_strlcpy(title.male_title,
8898 sz_strlcpy(title.female_title,
8903}
8904
8905/**********************************************************************/
8909static void send_ruleset_nations(struct conn_list *dest)
8910{
8911 struct packet_ruleset_nation_sets sets_packet;
8912 struct packet_ruleset_nation_groups groups_packet;
8913 struct packet_ruleset_nation packet;
8914 int i;
8915
8916 sets_packet.nsets = nation_set_count();
8917 i = 0;
8918 nation_sets_iterate(pset) {
8919 sz_strlcpy(sets_packet.names[i], nation_set_untranslated_name(pset));
8920 sz_strlcpy(sets_packet.rule_names[i], nation_set_rule_name(pset));
8921 sz_strlcpy(sets_packet.descriptions[i], nation_set_description(pset));
8922 i++;
8924 lsend_packet_ruleset_nation_sets(dest, &sets_packet);
8925
8926 groups_packet.ngroups = nation_group_count();
8927 i = 0;
8928 nation_groups_iterate(pgroup) {
8929 sz_strlcpy(groups_packet.groups[i],
8931 groups_packet.hidden[i] = pgroup->hidden;
8932 i++;
8934 lsend_packet_ruleset_nation_groups(dest, &groups_packet);
8935
8937 packet.id = nation_number(n);
8938 if (n->translation_domain == NULL) {
8939 packet.translation_domain[0] = '\0';
8940 } else {
8941 sz_strlcpy(packet.translation_domain, n->translation_domain);
8942 }
8943 sz_strlcpy(packet.adjective, untranslated_name(&n->adjective));
8944 sz_strlcpy(packet.rule_name, rule_name_get(&n->adjective));
8945 sz_strlcpy(packet.noun_plural, untranslated_name(&n->noun_plural));
8946 sz_strlcpy(packet.graphic_str, n->flag_graphic_str);
8947 sz_strlcpy(packet.graphic_alt, n->flag_graphic_alt);
8948
8949 i = 0;
8951 sz_strlcpy(packet.leader_name[i], nation_leader_name(pleader));
8952 packet.leader_is_male[i] = nation_leader_is_male(pleader);
8953 i++;
8955 packet.leader_count = i;
8956
8957 packet.style = style_number(n->style);
8958 packet.is_playable = n->is_playable;
8959 packet.barbarian_type = n->barb_type;
8960
8961 sz_strlcpy(packet.legend, n->legend);
8962
8963 i = 0;
8964 nation_set_list_iterate(n->sets, pset) {
8965 packet.sets[i++] = nation_set_number(pset);
8967 packet.nsets = i;
8968
8969 i = 0;
8970 nation_group_list_iterate(n->groups, pgroup) {
8971 packet.groups[i++] = nation_group_number(pgroup);
8973 packet.ngroups = i;
8974
8975 packet.init_government_id = n->init_government
8976 ? government_number(n->init_government) : government_count();
8977 fc_assert(ARRAY_SIZE(packet.init_techs) == ARRAY_SIZE(n->init_techs));
8978 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
8979 if (n->init_techs[i] != A_LAST) {
8980 packet.init_techs[i] = n->init_techs[i];
8981 } else {
8982 break;
8983 }
8984 }
8985 packet.init_techs_count = i;
8986 fc_assert(ARRAY_SIZE(packet.init_units) == ARRAY_SIZE(n->init_units));
8987 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
8988 const struct unit_type *t = n->init_units[i];
8989 if (t) {
8990 packet.init_units[i] = utype_number(t);
8991 } else {
8992 break;
8993 }
8994 }
8995 packet.init_units_count = i;
8997 == ARRAY_SIZE(n->init_buildings));
8998 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
8999 if (n->init_buildings[i] != B_LAST) {
9000 /* Impr_type_id to int */
9001 packet.init_buildings[i] = n->init_buildings[i];
9002 } else {
9003 break;
9004 }
9005 }
9006 packet.init_buildings_count = i;
9007
9008 lsend_packet_ruleset_nation(dest, &packet);
9010
9011 /* Send initial values of is_pickable */
9013}
9014
9015/**********************************************************************/
9019static void send_ruleset_styles(struct conn_list *dest)
9020{
9021 struct packet_ruleset_style packet;
9022
9023 styles_iterate(s) {
9024 packet.id = style_index(s);
9025 sz_strlcpy(packet.name, untranslated_name(&s->name));
9026 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
9027
9028 lsend_packet_ruleset_style(dest, &packet);
9030}
9031
9032/**********************************************************************/
9035static void send_ruleset_clauses(struct conn_list *dest)
9036{
9037 struct packet_ruleset_clause packet;
9038 int i;
9039
9040 for (i = 0; i < CLAUSE_COUNT; i++) {
9041 struct clause_info *info = clause_info_get(i);
9042 int j;
9043
9044 packet.type = i;
9045 packet.enabled = info->enabled;
9046
9047 j = 0;
9049 packet.giver_reqs[j++] = *preq;
9051 packet.giver_reqs_count = j;
9052
9053 j = 0;
9055 packet.receiver_reqs[j++] = *preq;
9057 packet.receiver_reqs_count = j;
9058
9059 lsend_packet_ruleset_clause(dest, &packet);
9060 }
9061}
9062
9063/**********************************************************************/
9067static void send_ruleset_multipliers(struct conn_list *dest)
9068{
9069 multipliers_iterate(pmul) {
9070 int j;
9071 struct packet_ruleset_multiplier packet;
9072
9073 packet.id = multiplier_number(pmul);
9074 packet.start = pmul->start;
9075 packet.stop = pmul->stop;
9076 packet.step = pmul->step;
9077 packet.def = pmul->def;
9078 packet.offset = pmul->offset;
9079 packet.factor = pmul->factor;
9080 packet.minimum_turns = pmul->minimum_turns;
9081
9082 sz_strlcpy(packet.name, untranslated_name(&pmul->name));
9083 sz_strlcpy(packet.rule_name, rule_name_get(&pmul->name));
9084
9085 j = 0;
9086 requirement_vector_iterate(&pmul->reqs, preq) {
9087 packet.reqs[j++] = *preq;
9089 packet.reqs_count = j;
9090
9091 PACKET_STRVEC_COMPUTE(packet.helptext, pmul->helptext);
9092
9093 lsend_packet_ruleset_multiplier(dest, &packet);
9095}
9096
9097/**********************************************************************/
9101static void send_ruleset_cities(struct conn_list *dest)
9102{
9103 struct packet_ruleset_city city_p;
9104 int k, j;
9105
9106 for (k = 0; k < game.control.styles_count; k++) {
9107 city_p.style_id = k;
9108
9109 j = 0;
9111 city_p.reqs[j++] = *preq;
9113 city_p.reqs_count = j;
9114
9120
9121 lsend_packet_ruleset_city(dest, &city_p);
9122 }
9123}
9124
9125/**********************************************************************/
9129static void send_ruleset_musics(struct conn_list *dest)
9130{
9131 struct packet_ruleset_music packet;
9132
9133 music_styles_iterate(pmus) {
9134 int j;
9135
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 j = 0;
9142 requirement_vector_iterate(&(pmus->reqs), preq) {
9143 packet.reqs[j++] = *preq;
9145 packet.reqs_count = j;
9146
9147 lsend_packet_ruleset_music(dest, &packet);
9149}
9150
9151/**********************************************************************/
9155static void send_ruleset_game(struct conn_list *dest)
9156{
9157 struct packet_ruleset_game misc_p;
9158 int i;
9159
9160 fc_assert_ret(game.veteran != NULL);
9161
9162 /* Per unit veteran system definition. */
9164
9165 for (i = 0; i < misc_p.veteran_levels; i++) {
9166 const struct veteran_level *vlevel = game.veteran->definitions + i;
9167
9168 sz_strlcpy(misc_p.veteran_name[i], untranslated_name(&vlevel->name));
9169 misc_p.power_fact[i] = vlevel->power_fact;
9170 misc_p.move_bonus[i] = vlevel->move_bonus;
9171 misc_p.base_raise_chance[i] = vlevel->base_raise_chance;
9172 misc_p.work_raise_chance[i] = vlevel->work_raise_chance;
9173 }
9174
9175 fc_assert(sizeof(misc_p.global_init_techs)
9176 == sizeof(game.rgame.global_init_techs));
9179 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9180 if (game.rgame.global_init_techs[i] != A_LAST) {
9182 } else {
9183 break;
9184 }
9185 }
9186 misc_p.global_init_techs_count = i;
9187
9190 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9192 /* Impr_type_id to int */
9193 misc_p.global_init_buildings[i] =
9195 } else {
9196 break;
9197 }
9198 }
9199 misc_p.global_init_buildings_count = i;
9200
9202
9204
9208
9209 lsend_packet_ruleset_game(dest, &misc_p);
9210}
9211
9212/**********************************************************************/
9216static void send_ruleset_team_names(struct conn_list *dest)
9217{
9218 struct packet_team_name_info team_name_info_p;
9219
9220 team_slots_iterate(tslot) {
9221 const char *name = team_slot_defined_name(tslot);
9222
9223 if (NULL == name) {
9224 /* End of defined names. */
9225 break;
9226 }
9227
9228 team_name_info_p.team_id = team_slot_index(tslot);
9229 sz_strlcpy(team_name_info_p.team_name, name);
9230
9231 lsend_packet_team_name_info(dest, &team_name_info_p);
9233}
9234
9235/**********************************************************************/
9238static void notify_ruleset_fallback(const char *msg)
9239{
9240 notify_conn(NULL, NULL, E_LOG_FATAL, ftc_warning, "%s", msg);
9241}
9242
9243/**********************************************************************/
9246bool load_rulesets(const char *restore, const char *alt, bool compat_mode,
9247 rs_conversion_logger logger,
9248 bool act, bool buffer_script, bool load_luadata)
9249{
9250 set_ruleset_compat_mode(compat_mode);
9251
9252 if (load_rulesetdir(game.server.rulesetdir, compat_mode, logger,
9253 act, buffer_script, load_luadata)) {
9255 return TRUE;
9256 }
9257
9258 if (alt != NULL) {
9259 if (load_rulesetdir(alt, compat_mode, logger, act, buffer_script,
9260 load_luadata)) {
9262
9264 return TRUE;
9265 }
9266 }
9267
9268 /* Fallback to previous one. */
9269 if (restore != NULL) {
9270 if (load_rulesetdir(restore, compat_mode, logger, act, buffer_script, TRUE)) {
9271 sz_strlcpy(game.server.rulesetdir, restore);
9272
9273 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Keeping previous one."));
9274
9276
9278
9279 /* We're in sane state as restoring previous ruleset succeeded,
9280 * but return failure to indicate that this is not what caller
9281 * wanted. */
9282 return FALSE;
9283 }
9284 }
9285
9287
9289
9290 /* Fallback to default one, but not if that's what we tried already */
9292 && (restore == NULL || strcmp(GAME_DEFAULT_RULESETDIR, restore))) {
9293 if (load_rulesetdir(GAME_DEFAULT_RULESETDIR, FALSE, NULL, act, buffer_script, TRUE)) {
9294 /* We're in sane state as fallback ruleset loading succeeded,
9295 * but return failure to indicate that this is not what caller
9296 * wanted. */
9298
9299 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Switching to default one."));
9300
9301 return FALSE;
9302 }
9303 }
9304
9305#ifdef FREECIV_WEB
9306 log_normal(_("Cannot load any ruleset. Freeciv-web ruleset is available from "
9307 "https://github.com/freeciv/freeciv-web"));
9308#endif /* FREECIV_WEB */
9309
9310 /* Cannot load even default ruleset, we're in completely unusable state */
9311 exit(EXIT_FAILURE);
9312
9314}
9315
9316/**********************************************************************/
9320{
9321 if (file != NULL) {
9322 secfile_destroy(file);
9323 }
9324}
9325
9326/**********************************************************************/
9331{
9333 requirement_vector_free(&reqs_list);
9334}
9335
9336/**********************************************************************/
9340static bool load_rulesetdir(const char *rsdir, bool compat_mode,
9341 rs_conversion_logger logger,
9342 bool act, bool buffer_script, bool load_luadata)
9343{
9344 struct section_file *techfile, *unitfile, *buildfile, *govfile, *terrfile;
9345 struct section_file *stylefile, *cityfile, *nationfile, *effectfile, *gamefile;
9346 bool ok = TRUE;
9347 struct rscompat_info compat_info;
9348
9349 log_normal(_("Loading rulesets."));
9350
9351 rscompat_init_info(&compat_info);
9352 compat_info.compat_mode = compat_mode;
9353 compat_info.log_cb = logger;
9354
9356 /* Reset the list of available player colors. */
9360
9361 if (script_buffer != NULL) {
9363 script_buffer = NULL;
9364 }
9365 if (parser_buffer != NULL) {
9367 parser_buffer = NULL;
9368 }
9369
9370 server.playable_nations = 0;
9371
9372 techfile = openload_ruleset_file("techs", rsdir);
9373 buildfile = openload_ruleset_file("buildings", rsdir);
9374 govfile = openload_ruleset_file("governments", rsdir);
9375 unitfile = openload_ruleset_file("units", rsdir);
9376 terrfile = openload_ruleset_file("terrain", rsdir);
9377 stylefile = openload_ruleset_file("styles", rsdir);
9378 cityfile = openload_ruleset_file("cities", rsdir);
9379 nationfile = openload_ruleset_file("nations", rsdir);
9380 effectfile = openload_ruleset_file("effects", rsdir);
9381 gamefile = openload_ruleset_file("game", rsdir);
9382 if (load_luadata) {
9384 } else {
9385 game.server.luadata = NULL;
9386 }
9387
9388 if (techfile == NULL
9389 || buildfile == NULL
9390 || govfile == NULL
9391 || unitfile == NULL
9392 || terrfile == NULL
9393 || stylefile == NULL
9394 || cityfile == NULL
9395 || nationfile == NULL
9396 || effectfile == NULL
9397 || gamefile == NULL) {
9398 ok = FALSE;
9399 }
9400
9401 if (ok) {
9402 /* Note: Keep load_game_names first so that compat_info.version is
9403 * correctly initialized. */
9404 ok = load_game_names(gamefile, &compat_info)
9405 && load_tech_names(techfile, &compat_info)
9406 && load_building_names(buildfile, &compat_info)
9407 && load_government_names(govfile, &compat_info)
9408 && load_unit_names(unitfile, &compat_info)
9409 && load_terrain_names(terrfile, &compat_info)
9410 && load_style_names(stylefile, &compat_info)
9411 && load_nation_names(nationfile, &compat_info);
9412 }
9413
9414 if (ok) {
9415 ok = rscompat_names(&compat_info);
9416 }
9417
9418 if (ok) {
9419 ok = load_ruleset_techs(techfile, &compat_info);
9420 }
9421 if (ok) {
9422 ok = load_ruleset_styles(stylefile, &compat_info);
9423 }
9424 if (ok) {
9425 ok = load_ruleset_cities(cityfile, &compat_info);
9426 }
9427 if (ok) {
9428 ok = load_ruleset_governments(govfile, &compat_info);
9429 }
9430 if (ok) {
9431 /* terrain must precede nations and units */
9432 ok = load_ruleset_terrain(terrfile, &compat_info);
9433 }
9434 if (ok) {
9435 ok = load_ruleset_units(unitfile, &compat_info);
9436 }
9437 if (ok) {
9438 ok = load_ruleset_buildings(buildfile, &compat_info);
9439 }
9440 if (ok) {
9441 ok = load_ruleset_nations(nationfile, &compat_info);
9442 }
9443 if (ok) {
9444 ok = load_ruleset_effects(effectfile, &compat_info);
9445 }
9446 if (ok) {
9447 ok = load_ruleset_game(gamefile, act, &compat_info);
9448 }
9449
9450 if (ok) {
9451 rscompat_adjust_pre_sanity(&compat_info);
9452
9453 /* Init nations we just loaded. */
9455
9456 /* Needed by role_unit_precalcs(). */
9458
9459 /* Prepare caches we want to sanity check. */
9463
9465 && sanity_check_ruleset_data(&compat_info);
9466 }
9467
9468 if (ok) {
9469 /* Only load settings for a sane ruleset */
9470 ok = settings_ruleset(gamefile, "settings", act);
9471
9472 if (ok) {
9473 secfile_check_unused(gamefile);
9474 }
9475 }
9476
9477 nullcheck_secfile_destroy(techfile);
9478 nullcheck_secfile_destroy(stylefile);
9479 nullcheck_secfile_destroy(cityfile);
9481 nullcheck_secfile_destroy(terrfile);
9482 nullcheck_secfile_destroy(unitfile);
9483 nullcheck_secfile_destroy(buildfile);
9484 nullcheck_secfile_destroy(nationfile);
9485 nullcheck_secfile_destroy(effectfile);
9486 nullcheck_secfile_destroy(gamefile);
9487
9488 if (extra_sections) {
9489 free(extra_sections);
9490 extra_sections = NULL;
9491 }
9492 if (base_sections) {
9493 free(base_sections);
9494 base_sections = NULL;
9495 }
9496 if (road_sections) {
9497 free(road_sections);
9498 road_sections = NULL;
9499 }
9500 if (resource_sections) {
9501 free(resource_sections);
9502 resource_sections = NULL;
9503 }
9504 if (terrain_sections) {
9505 free(terrain_sections);
9506 terrain_sections = NULL;
9507 }
9508
9509 if (ok) {
9510 rscompat_postprocess(&compat_info);
9511 }
9512
9513 if (ok) {
9514 char **buffer = buffer_script ? &script_buffer : NULL;
9515
9517
9519
9520 ok = (openload_script_file("script", rsdir, buffer, FALSE) == TRI_YES);
9521 }
9522
9523 if (ok) {
9524 enum fc_tristate pret;
9525 char **buffer = buffer_script ? &parser_buffer : NULL;
9526
9527 pret = openload_script_file("parser", rsdir, buffer, compat_info.compat_mode);
9528
9529 if (pret == TRI_MAYBE && buffer_script) {
9531 "-- This file is for lua-functionality for parsing luadata.txt\n-- of this ruleset.");
9532 }
9533
9534 ok = (pret != TRI_NO);
9535 }
9536
9537 if (ok && !buffer_script) {
9538 ok = (openload_script_file("default", rsdir, NULL, FALSE) == TRI_YES);
9539 }
9540
9541 if (ok && act) {
9542 /* Populate remaining caches. */
9545 unit_class_iterate(pclass) {
9546 set_unit_class_caches(pclass);
9548 unit_type_iterate(ptype) {
9549 ptype->unknown_move_cost = utype_unknown_move_cost(ptype);
9550 set_unit_type_caches(ptype);
9553
9554 /* Build advisors unit class cache corresponding to loaded rulesets */
9556 CALL_FUNC_EACH_AI(units_ruleset_init);
9557
9558 /* We may need to adjust the number of AI players
9559 * if the number of available nations changed. */
9560 (void) aifill(game.info.aifill);
9561 }
9562
9563 return ok;
9564}
9565
9566/**********************************************************************/
9570{
9571 struct section_file *file;
9572 bool ok = TRUE;
9573
9575 if (file == NULL) {
9577 "Could not load game.ruleset:\n%s",
9578 secfile_error());
9579 ok = FALSE;
9580 }
9581 if (ok) {
9582 settings_ruleset(file, "settings", TRUE);
9583 secfile_destroy(file);
9584 }
9585
9586 return ok;
9587}
9588
9589/**********************************************************************/
9592void send_rulesets(struct conn_list *dest)
9593{
9595
9596 /* ruleset_control also indicates to client that ruleset sending starts. */
9598
9599 /* Currently containing control-kind of data of nation sets and groups,
9600 * this too must be sent before any requirement vector may depend on
9601 * that data. */
9603
9604 send_ruleset_game(dest);
9613 send_ruleset_techs(dest);
9616 send_ruleset_units(dest);
9618 send_ruleset_extras(dest);
9619 send_ruleset_bases(dest);
9620 send_ruleset_roads(dest);
9623 send_ruleset_goods(dest);
9625 send_ruleset_styles(dest);
9627 send_ruleset_cities(dest);
9629 send_ruleset_musics(dest);
9630 send_ruleset_cache(dest);
9631
9632 /* Indicate client that all rulesets have now been sent. */
9634
9635 /* changed game settings will be send in
9636 * connecthand.c:establish_new_connection() */
9637
9639}
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:7353
void actions_rs_pre_san_gen(void)
Definition actions.c:1520
const char * action_min_range_ruleset_var_name(int act)
Definition actions.c:7966
const char * action_blocked_by_ruleset_var_name(const struct action *act)
Definition actions.c:9034
bool action_is_in_use(struct action *paction)
Definition actions.c:7330
const char * action_post_success_forced_ruleset_var_name(const struct action *act)
Definition actions.c:9176
struct action * action_by_rule_name(const char *name)
Definition actions.c:1708
const char * action_rule_name(const struct action *action)
Definition actions.c:1876
const char * action_actor_consuming_always_ruleset_var_name(action_id act)
Definition actions.c:8899
const char * action_max_range_ruleset_var_name(int act)
Definition actions.c:8177
enum action_target_kind action_target_kind_default(enum action_result result)
Definition actions.c:8528
int action_min_range_default(enum action_result result)
Definition actions.c:8095
const char * action_target_kind_ruleset_var_name(int act)
Definition actions.c:8398
void action_enabler_add(struct action_enabler *enabler)
Definition actions.c:2442
const char * action_ui_name_default(int act)
Definition actions.c:7664
struct action_enabler * action_enabler_new(void)
Definition actions.c:2396
bool action_enabler_possible_actor(const struct action_enabler *ae)
Definition actions.c:7274
struct action_enabler_list * action_enablers_for_action(action_id action)
Definition actions.c:2475
const char * action_ui_name_ruleset_var_name(int act)
Definition actions.c:7438
int action_max_range_default(enum action_result result)
Definition actions.c:8312
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:488
#define action_auto_perf_iterate_end
Definition actions.h:593
#define action_enablers_iterate_end
Definition actions.h:526
#define ACTION_AUTO_MOVED_ADJ
Definition actions.h:617
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:659
#define ACTION_AUTO_UPKEEP_GOLD
Definition actions.h:615
static struct action * action_by_number(action_id act_id)
Definition actions.h:638
#define NUM_ACTIONS
Definition actions.h:297
#define ACTION_AUTO_ESCAPE_STACK
Definition actions.h:621
#define action_has_result(_act_, _res_)
Definition actions.h:448
#define ACTION_AUTO_ESCAPE_CITY
Definition actions.h:620
#define action_enabler_list_iterate_end
Definition actions.h:457
#define ACTION_DISTANCE_UNLIMITED
Definition actions.h:352
#define action_by_result_iterate_end
Definition actions.h:492
#define ACTION_AUTO_UPKEEP_SHIELD
Definition actions.h:616
#define ACTION_AUTO_POST_BRIBE
Definition actions.h:618
#define action_iterate_end
Definition actions.h:472
#define action_enablers_iterate(_enabler_)
Definition actions.h:520
#define action_enabler_list_iterate(action_enabler_list, aenabler)
Definition actions.h:455
#define action_iterate(_act_)
Definition actions.h:467
#define action_auto_perf_iterate(_act_perf_)
Definition actions.h:581
#define ACTION_AUTO_UPKEEP_FOOD
Definition actions.h:614
#define ACTION_AUTO_POST_ATTACK
Definition actions.h:619
#define ACTION_NONE
Definition actions.h:293
void adv_units_ruleset_init(void)
Definition advruleset.c:33
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:384
#define str
Definition astring.c:76
#define n
Definition astring.c:77
Base_type_id base_number(const struct base_type *pbase)
Definition base.c:92
void base_type_init(struct extra_type *pextra, int idx)
Definition base.c:117
bool territory_claiming_base(const struct base_type *pbase)
Definition base.c:158
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
struct citystyle * city_styles
Definition city.c:79
void city_styles_alloc(int num)
Definition city.c:3305
void city_production_caravan_shields_init(void)
Definition city.c:1747
const char * city_style_rule_name(const int style)
Definition city.c:1734
const char * get_output_identifier(Output_type_id output)
Definition city.c:614
#define output_type_iterate(output)
Definition city.h:812
#define output_type_iterate_end
Definition city.h:818
static struct fc_sockaddr_list * list
Definition clinet.c:102
void conn_list_compression_thaw(const struct conn_list *pconn_list)
Definition connection.c:729
void conn_list_compression_freeze(const struct conn_list *pconn_list)
Definition connection.c:717
#define MAX_LEN_CONTENT
Definition connection.h:59
#define log_deprecation(message,...)
struct clause_info * clause_info_get(enum clause_type type)
Definition diptreaty.c:273
const char * disaster_rule_name(struct disaster_type *pdis)
Definition disaster.c:105
Disaster_type_id disaster_number(const struct disaster_type *pdis)
Definition disaster.c:56
Disaster_type_id disaster_index(const struct disaster_type *pdis)
Definition disaster.c:69
#define disaster_type_iterate(_p)
Definition disaster.h:80
#define disaster_type_iterate_end
Definition disaster.h:86
int int id
Definition editgui_g.h:28
struct @21::@22 reqs
void send_ruleset_cache(struct conn_list *dest)
Definition effects.c:553
struct effect * effect_new(enum effect_type type, int value, struct multiplier *pmul)
Definition effects.c:179
struct effect_list * get_effects(enum effect_type effect_type)
Definition effects.c:136
void effect_req_append(struct effect *peffect, struct requirement req)
Definition effects.c:229
#define effect_list_iterate_end
Definition effects.h:375
#define effect_list_iterate(effect_list, peffect)
Definition effects.h:373
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:204
const char * extra_flag_helptxt(enum extra_flag_id id)
Definition extras.c:923
void set_user_extra_flag_name(enum extra_flag_id id, const char *name, const char *helptxt)
Definition extras.c:882
bool is_extra_caused_by_worker_action(const struct extra_type *pextra)
Definition extras.c:981
int extra_number(const struct extra_type *pextra)
Definition extras.c:153
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:810
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:241
void extra_to_caused_by_list(struct extra_type *pextra, enum extra_cause cause)
Definition extras.c:296
struct extra_type * extra_by_number(int id)
Definition extras.c:175
void extra_to_removed_by_list(struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:316
struct extra_type_list * extra_type_list_of_terr_claimers(void)
Definition extras.c:259
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:195
bool is_extra_removed_by(const struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:327
struct extra_type_list * extra_type_list_of_unit_hiders(void)
Definition extras.c:251
#define extra_type_iterate(_p)
Definition extras.h:291
#define extra_type_iterate_end
Definition extras.h:297
#define is_extra_caused_by(e, c)
Definition extras.h:196
#define extra_index(_e_)
Definition extras.h:177
#define extra_base_get(_e_)
Definition extras.h:184
#define extra_road_get(_e_)
Definition extras.h:185
#define extra_type_by_cause_iterate_end
Definition extras.h:315
#define MAX_NUM_USER_EXTRA_FLAGS
Definition extras.h:80
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:309
#define MAX_DISASTER_TYPES
Definition fc_types.h:52
#define MAX_VET_LEVELS
Definition fc_types.h:49
@ ROCO_RAILROAD
Definition fc_types.h:1105
@ ROCO_NONE
Definition fc_types.h:1105
@ ROCO_RIVER
Definition fc_types.h:1105
@ ROCO_ROAD
Definition fc_types.h:1105
#define MAX_GRANARY_INIS
Definition fc_types.h:72
#define MAX_NUM_NATIONS
Definition fc_types.h:60
#define MAX_NUM_BUILDING_LIST
Definition fc_types.h:46
#define MAX_NUM_REQS
Definition fc_types.h:380
#define MAX_GOODS_TYPES
Definition fc_types.h:51
#define EC_NATURAL_DEFENSIVE
Definition fc_types.h:970
#define EC_SPECIAL
Definition fc_types.h:968
int action_id
Definition fc_types.h:359
#define SP_MAX
Definition fc_types.h:379
#define EC_NONE
Definition fc_types.h:967
#define EC_NOT_AGGRESSIVE
Definition fc_types.h:971
#define EC_DEFENSIVE
Definition fc_types.h:969
#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
#define MAX_ACHIEVEMENT_TYPES
Definition fc_types.h:53
#define MAX_LEN_NAME
Definition fc_types.h:66
#define MAX_NUM_TECH_LIST
Definition fc_types.h:44
#define MAX_LEN_CITYNAME
Definition fc_types.h:67
#define UCL_LAST
Definition fc_types.h:387
#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:57
void game_ruleset_init(void)
Definition game.c:499
void game_ruleset_free(void)
Definition game.c:544
struct world wld
Definition game.c:58
#define RS_DEFAULT_RANSOM_GOLD
Definition game.h:840
#define RS_DEFAULT_GRANARY_FOOD_INI
Definition game.h:789
#define RS_DEFAULT_CIVIL_WAR_UNHAPPY
Definition game.h:826
#define RS_DEFAULT_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:832
#define RS_MIN_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:770
#define RS_MAX_TECH_UPKEEP_DIVIDER
Definition game.h:852
#define RS_MIN_ILLNESS_POLLUTION_PCT
Definition game.h:756
#define RS_DEFAULT_NUKE_POP_LOSS_PCT
Definition game.h:829
#define RS_MAX_BORDER_RADIUS_SQ_CITY
Definition game.h:763
#define RS_DEFAULT_BASE_POLLUTION
Definition game.h:812
#define RS_MIN_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:752
#define RS_MAX_ILLNESS_BASE_FACTOR
Definition game.h:745
#define RS_DEFAULT_INCITE_TOTAL_FCT
Definition game.h:785
#define RS_DEFAULT_ILLNESS_BASE_FACTOR
Definition game.h:743
#define RS_DEFAULT_NEG_YEAR_LABEL
Definition game.h:739
#define RS_MIN_NUKE_POP_LOSS_PCT
Definition game.h:830
#define RS_MIN_INCITE_IMPROVEMENT_FCT
Definition game.h:778
#define RS_MIN_FOOD_COST
Definition game.h:822
#define RS_MIN_BASE_BRIBE_COST
Definition game.h:837
#define RS_MAX_NUKE_POP_LOSS_PCT
Definition game.h:831
#define RS_DEFAULT_INCITE_IMPROVEMENT_FCT
Definition game.h:777
#define RS_MAX_INCITE_IMPROVEMENT_FCT
Definition game.h:779
#define RS_MIN_RANSOM_GOLD
Definition game.h:841
#define RS_ACTION_NO_MAX_DISTANCE
Definition game.h:866
#define RS_DEFAULT_BASE_BRIBE_COST
Definition game.h:836
#define RS_MAX_INCITE_BASE_COST
Definition game.h:775
#define RS_DEFAULT_TECH_UPKEEP_DIVIDER
Definition game.h:850
#define RS_DEFAULT_HAPPY_COST
Definition game.h:817
#define RS_MIN_UPGRADE_VETERAN_LOSS
Definition game.h:847
#define RS_MIN_ILLNESS_MIN_SIZE
Definition game.h:748
#define RS_DEFAULT_POISON_EMPTIES_FOOD_STOCK
Definition game.h:858
#define RS_DEFAULT_GRANARY_FOOD_INC
Definition game.h:791
#define RS_DEFAULT_ILLNESS_ON
Definition game.h:741
#define RS_MAX_FOOD_COST
Definition game.h:823
#define RS_MAX_HAPPY_COST
Definition game.h:819
#define GAME_DEFAULT_CELEBRATESIZE
Definition game.h:480
#define RS_MIN_ILLNESS_BASE_FACTOR
Definition game.h:744
#define RS_DEFAULT_STEAL_MAP_REVEALS_CITIES
Definition game.h:859
#define RS_MIN_TECH_UPKEEP_DIVIDER
Definition game.h:851
#define RS_MAX_RANSOM_GOLD
Definition game.h:842
#define RS_MIN_HAPPY_COST
Definition game.h:818
#define RS_MIN_BORDER_RADIUS_SQ_CITY
Definition game.h:762
#define GAME_DEFAULT_RULESETDIR
Definition game.h:654
#define RS_DEFAULT_CIVIL_WAR_CELEB
Definition game.h:825
#define RS_MAX_BASE_TECH_COST
Definition game.h:856
#define RS_DEFAULT_BASE_TECH_COST
Definition game.h:854
#define RS_MIN_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:833
#define RS_MAX_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:771
#define RS_DEFAULT_UPGRADE_VETERAN_LOSS
Definition game.h:846
#define RS_MAX_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:834
#define RS_MAX_INCITE_UNIT_FCT
Definition game.h:783
#define RS_MIN_VIS_RADIUS_SQ
Definition game.h:809
#define RS_DEFAULT_CALENDAR_SKIP_0
Definition game.h:759
#define RS_MAX_ILLNESS_MIN_SIZE
Definition game.h:749
#define RS_DEFAULT_CITY_RADIUS_SQ
Definition game.h:804
#define GAME_DEFAULT_START_YEAR
Definition game.h:715
#define RS_MAX_BORDER_SIZE_EFFECT
Definition game.h:767
#define RS_DEFAULT_BORDER_SIZE_EFFECT
Definition game.h:765
#define RS_MAX_BASE_BRIBE_COST
Definition game.h:838
#define RS_MIN_INCITE_BASE_COST
Definition game.h:774
#define RS_DEFAULT_PILLAGE_SELECT
Definition game.h:844
#define RS_MIN_CITY_RADIUS_SQ
Definition game.h:805
#define RS_MIN_CITY_CENTER_OUTPUT
Definition game.h:796
#define RS_MAX_GRANARY_FOOD_INC
Definition game.h:793
#define RS_MAX_CITY_CENTER_OUTPUT
Definition game.h:797
#define RS_MAX_CITY_RADIUS_SQ
Definition game.h:806
#define RS_DEFAULT_POS_YEAR_LABEL
Definition game.h:737
#define RS_MIN_INCITE_UNIT_FCT
Definition game.h:782
#define RS_MIN_BORDER_SIZE_EFFECT
Definition game.h:766
#define RS_DEFAULT_VIS_RADIUS_SQ
Definition game.h:808
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:769
#define RS_DEFAULT_TIRED_ATTACK
Definition game.h:828
#define RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS
Definition game.h:860
#define RS_MAX_ILLNESS_POLLUTION_PCT
Definition game.h:757
#define RS_DEFAULT_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:751
#define RS_DEFAULT_FOOD_COST
Definition game.h:821
#define RS_DEFAULT_INCITE_UNIT_FCT
Definition game.h:781
#define RS_MAX_INCITE_TOTAL_FCT
Definition game.h:787
#define RS_DEFAULT_INCITE_BASE_COST
Definition game.h:773
#define GAME_DEFAULT_ANGRYCITIZEN
Definition game.h:371
#define RS_DEFAULT_CITY_CENTER_OUTPUT
Definition game.h:795
#define RS_MIN_INCITE_TOTAL_FCT
Definition game.h:786
#define RS_DEFAULT_ILLNESS_POLLUTION_PCT
Definition game.h:755
#define RS_MAX_UPGRADE_VETERAN_LOSS
Definition game.h:848
static void set_ruleset_compat_mode(bool active)
Definition game.h:332
#define RS_MAX_VIS_RADIUS_SQ
Definition game.h:810
#define RS_MIN_GRANARY_FOOD_INC
Definition game.h:792
#define RS_MAX_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:753
#define RS_DEFAULT_ILLNESS_MIN_SIZE
Definition game.h:747
#define RS_MIN_BASE_TECH_COST
Definition game.h:855
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY
Definition game.h:761
const struct nation_type * ruler_title_nation(const struct ruler_title *pruler_title)
Definition government.c:364
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:324
const char * ruler_title_female_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:382
Government_type_id government_count(void)
Definition government.c:70
const char * ruler_title_male_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:373
void governments_alloc(int num)
Definition government.c:527
Government_type_id government_number(const struct government *pgovern)
Definition government.c:90
const struct ruler_title_hash * government_ruler_titles(const struct government *pgovern)
Definition government.c:313
Government_type_id government_index(const struct government *pgovern)
Definition government.c:81
const char * government_rule_name(const struct government *pgovern)
Definition government.c:132
struct government * government_by_rule_name(const char *name)
Definition government.c:54
#define governments_iterate(NAME_pgov)
Definition government.h:120
#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:123
const char * title
Definition repodlgs.c:1313
GType type
Definition repodlgs.c:1312
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:90
struct impr_type * improvement_by_rule_name(const char *name)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define B_NEVER
Definition improvement.h:44
#define B_LAST
Definition improvement.h:42
const char * name
Definition inputfile.c:127
void vdo_log(const char *file, const char *function, int line, bool print_from_where, enum log_level level, char *buf, int buflen, const char *message, va_list args)
Definition log.c:403
#define fc_assert_ret(condition)
Definition log.h:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define MAX_LEN_LOG_LINE
Definition log.h:26
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_do_output_for_level(level)
Definition log.h:89
#define log_debug(message,...)
Definition log.h:115
#define log_normal(message,...)
Definition log.h:107
log_level
Definition log.h:28
@ LOG_ERROR
Definition log.h:30
@ LOG_FATAL
Definition log.h:29
#define log_error(message,...)
Definition log.h:103
struct terrain_misc terrain_control
Definition map.c:69
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
int utype_unknown_move_cost(const struct unit_type *utype)
Definition movement.c:105
void init_move_fragments(void)
Definition movement.c:885
#define SINGLE_MOVE
Definition movement.h:24
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:1046
const char * nation_group_untranslated_name(const struct nation_group *pgroup)
Definition nation.c:1068
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1020
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:137
Nation_type_id nation_count(void)
Definition nation.c:506
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:485
struct nation_group * nation_group_new(const char *name)
Definition nation.c:959
bool nation_leader_is_male(const struct nation_leader *pleader)
Definition nation.c:289
struct nation_set * nation_set_new(const char *set_name, const char *set_rule_name, const char *set_description)
Definition nation.c:715
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:474
struct nation_city * nation_city_new(struct nation_type *pnation, const char *name)
Definition nation.c:341
const struct nation_leader_list * nation_leaders(const struct nation_type *pnation)
Definition nation.c:229
const char * nation_set_untranslated_name(const struct nation_set *pset)
Definition nation.c:796
bool is_nation_playable(const struct nation_type *nation)
Definition nation.c:199
int nation_set_number(const struct nation_set *pset)
Definition nation.c:707
void nation_city_set_terrain_preference(struct nation_city *pncity, const struct terrain *pterrain, enum nation_city_preference prefer)
Definition nation.c:389
void nation_city_set_river_preference(struct nation_city *pncity, enum nation_city_preference prefer)
Definition nation.c:401
bool nation_is_in_set(const struct nation_type *pnation, const struct nation_set *pset)
Definition nation.c:836
const char * nation_set_description(const struct nation_set *pset)
Definition nation.c:827
int nation_set_count(void)
Definition nation.c:690
struct nation_set * nation_set_by_number(int id)
Definition nation.c:761
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:120
struct nation_set * nation_set_by_rule_name(const char *name)
Definition nation.c:778
Nation_type_id nation_index(const struct nation_type *pnation)
Definition nation.c:497
const char * nation_leader_name(const struct nation_leader *pleader)
Definition nation.c:280
int nation_group_count(void)
Definition nation.c:934
const char * nation_set_rule_name(const struct nation_set *pset)
Definition nation.c:806
struct nation_leader * nation_leader_new(struct nation_type *pnation, const char *name, bool is_male)
Definition nation.c:238
void nation_group_set_hidden(struct nation_group *pgroup, bool hidden)
Definition nation.c:1036
void nations_alloc(int num)
Definition nation.c:621
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:210
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:951
#define nation_leader_list_iterate(leaderlist, pleader)
Definition nation.h:56
#define nation_sets_iterate_end
Definition nation.h:304
#define nation_set_list_iterate_end
Definition nation.h:67
#define nation_group_list_iterate(grouplist, pgroup)
Definition nation.h:74
#define nation_sets_iterate(NAME_pset)
Definition nation.h:300
#define nations_iterate_end
Definition nation.h:335
nation_city_preference
Definition nation.h:38
@ NCP_DISLIKE
Definition nation.h:39
@ NCP_LIKE
Definition nation.h:41
#define nations_iterate(NAME_pnation)
Definition nation.h:332
#define nation_leader_list_iterate_end
Definition nation.h:58
#define nation_group_list_iterate_end
Definition nation.h:76
#define nation_set_list_iterate(setlist, pset)
Definition nation.h:65
#define nation_groups_iterate(NAME_pgroup)
Definition nation.h:310
#define nation_groups_iterate_end
Definition nation.h:314
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:239
#define MAX_LEN_MSG
Definition packets.h:43
#define web_lsend_packet(packetname,...)
Definition packets.h:53
#define PACKET_STRVEC_COMPUTE(str, strvec)
Definition packets.h:205
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_rulesets_ready(struct conn_list *dest)
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:117
int len
Definition packhand.c:125
void send_nation_availability(struct conn_list *dest, bool nationset_change)
Definition plrhand.c:2471
void playercolor_free(void)
Definition plrhand.c:3171
void playercolor_init(void)
Definition plrhand.c:3162
int playercolor_count(void)
Definition plrhand.c:3210
void playercolor_add(struct rgbcolor *prgbcolor)
Definition plrhand.c:3190
void count_playable_nations(void)
Definition plrhand.c:2428
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:50
const char * secfile_error(void)
const char * section_name(const struct section *psection)
void secfile_destroy(struct section_file *secfile)
bool entry_bool_get(const struct entry *pentry, bool *value)
void secfile_check_unused(const struct section_file *secfile)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
struct section_list * secfile_sections_by_name_prefix(const struct section_file *secfile, const char *prefix)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
const char * entry_name(const struct entry *pentry)
struct entry * secfile_entry_lookup(const struct section_file *secfile, const char *path,...)
bool entry_str_get(const struct entry *pentry, const char **value)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
int * secfile_lookup_int_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
struct entry * section_entry_by_name(const struct section *psection, const char *name)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
bool entry_int_get(const struct entry *pentry, int *value)
const char * secfile_name(const struct section_file *secfile)
struct entry * secfile_entry_by_path(const struct section_file *secfile, const char *path)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
int secfile_lookup_int_def_min_max(const struct section_file *secfile, int defval, int minval, int maxval, const char *path,...)
enum entry_type entry_type_get(const struct entry *pentry)
@ ENTRY_FILEREFERENCE
@ ENTRY_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
const char * rscompat_action_ui_name_S3_1(struct rscompat_info *compat, int act_id)
Definition rscompat.c:2238
void rscompat_adjust_pre_sanity(struct rscompat_info *info)
Definition rscompat.c:839
enum road_gui_type rscompat_road_gui_type_3_1(struct road_type *proad)
Definition rscompat.c:2220
void rscompat_extra_adjust_3_1(struct rscompat_info *compat, struct extra_type *pextra)
Definition rscompat.c:2204
void rscompat_uclass_flags_3_1(struct rscompat_info *compat, struct unit_class *pclass)
Definition rscompat.c:2192
const char * rscompat_req_name_3_1(const char *type, const char *old_name)
Definition rscompat.c:2059
bool rscompat_auto_attack_3_1(struct rscompat_info *compat, struct action_auto_perf *auto_perf, size_t psize, enum unit_type_flag_id *protecor_flag)
Definition rscompat.c:1749
bool rscompat_old_effect_3_1(const char *type, struct section_file *file, const char *sec_name, struct rscompat_info *compat)
Definition rscompat.c:806
bool rscompat_names(struct rscompat_info *info)
Definition rscompat.c:386
const char * rscompat_utype_flag_name_3_1(struct rscompat_info *compat, const char *old_type)
Definition rscompat.c:2165
void rscompat_req_vec_adjust_3_1(struct rscompat_info *compat, struct requirement_vector *preqs, int *reqs_count, const char *filename, const char *sec, const char *sub, const char *rfor)
Definition rscompat.c:2079
bool rscompat_old_slow_invasions_3_1(struct rscompat_info *compat, bool slow_invasions)
Definition rscompat.c:1908
void rscompat_postprocess(struct rscompat_info *info)
Definition rscompat.c:859
int rscompat_check_capabilities(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:65
void rscompat_enablers_add_obligatory_hard_reqs(void)
Definition rscompat.c:285
const char * rscompat_action_max_range_name_S3_1(struct rscompat_info *compat, int act_id)
Definition rscompat.c:2253
void rscompat_init_info(struct rscompat_info *info)
Definition rscompat.c:56
bool rscompat_check_cap_and_version(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:131
const char * rscompat_combat_bonus_name_3_1(struct rscompat_info *compat, const char *old_type)
Definition rscompat.c:2177
const char * rscompat_req_type_name_3_1(const char *old_type)
Definition rscompat.c:2043
bool sanity_check_ruleset_data(struct rscompat_info *compat)
Definition rssanity.c:836
bool autoadjust_ruleset_data(void)
Definition rssanity.c:1517
#define check_cityname(name)
Definition ruleset.c:112
static int ruleset_purge_redundant_reqs_enablers(void)
Definition ruleset.c:414
static void ruleset_load_traits(struct trait_limits *out, struct section_file *file, const char *secname, const char *field_prefix)
Definition ruleset.c:1324
static bool load_rulesetdir(const char *rsdir, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleset.c:9340
#define STYLE_SECTION_PREFIX
Definition ruleset.c:95
static bool lookup_terrain(struct section_file *file, const char *entry, const char *filename, struct terrain *pthis, struct terrain **result, bool null_acceptable)
Definition ruleset.c:1225
static bool load_terrain_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2810
static bool load_style_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5716
int ruleset_purge_unused_entities(void)
Definition ruleset.c:304
#define MUSICSTYLE_SECTION_PREFIX
Definition ruleset.c:89
static char * road_sections
Definition ruleset.c:123
static bool load_ruleset_governments(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:4437
#define MULTIPLIER_SECTION_PREFIX
Definition ruleset.c:109
static struct requirement_vector reqs_list
Definition ruleset.c:125
static void send_ruleset_techs(struct conn_list *dest)
Definition ruleset.c:8240
#define section_strlcpy(dst, src)
Definition ruleset.c:117
#define check_name(name)
Definition ruleset.c:111
static void send_ruleset_units(struct conn_list *dest)
Definition ruleset.c:8053
static void send_ruleset_governments(struct conn_list *dest)
Definition ruleset.c:8866
static struct extra_type * lookup_resource(const char *filename, const char *name, const char *jsection)
Definition ruleset.c:1204
static struct section_file * openload_luadata_file(const char *rsdir)
Definition ruleset.c:617
static bool load_ruleset_techs(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1573
static bool purge_unused_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleset.c:318
void rulesets_deinit(void)
Definition ruleset.c:9330
static bool load_action_ui_name(struct section_file *file, int act, const char *entry_name, const char *compat_name)
Definition ruleset.c:6297
static void send_ruleset_resources(struct conn_list *dest)
Definition ruleset.c:8473
static bool load_ruleset_buildings(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2692
static char * terrain_sections
Definition ruleset.c:120
static bool lookup_building_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleset.c:1056
static void nullcheck_secfile_destroy(struct section_file *file)
Definition ruleset.c:9319
static void send_ruleset_clauses(struct conn_list *dest)
Definition ruleset.c:9035
static void send_ruleset_game(struct conn_list *dest)
Definition ruleset.c:9155
char * parser_buffer
Definition ruleset.c:200
#define NATION_SECTION_PREFIX
Definition ruleset.c:94
static bool load_ruleset_effects(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:6161
static void send_ruleset_nations(struct conn_list *dest)
Definition ruleset.c:8909
static void send_ruleset_roads(struct conn_list *dest)
Definition ruleset.c:8628
static int ruleset_purge_unused_enablers(void)
Definition ruleset.c:235
static bool is_on_allowed_list(const char *name, const char **list, size_t len)
Definition ruleset.c:4827
static void send_ruleset_tech_classes(struct conn_list *dest)
Definition ruleset.c:8222
static void send_ruleset_action_enablers(struct conn_list *dest)
Definition ruleset.c:8781
static void send_ruleset_control(struct conn_list *dest)
Definition ruleset.c:4629
bool load_rulesets(const char *restore, const char *alt, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleset.c:9246
#define GOODS_SECTION_PREFIX
Definition ruleset.c:101
void ruleset_error_real(rs_conversion_logger logger, const char *file, const char *function, int line, enum log_level level, const char *format,...)
Definition ruleset.c:206
#define TERRAIN_SECTION_PREFIX
Definition ruleset.c:103
static struct section_file * openload_ruleset_file(const char *whichset, const char *rsdir)
Definition ruleset.c:562
static void send_ruleset_musics(struct conn_list *dest)
Definition ruleset.c:9129
int ruleset_purge_redundant_reqs(void)
Definition ruleset.c:481
static int secfile_lookup_int_default_min_max(struct section_file *file, int def, int min, int max, const char *path,...) fc__attribute((__format__(__printf__
Definition ruleset.c:6259
static char * base_sections
Definition ruleset.c:122
#define DISASTER_SECTION_PREFIX
Definition ruleset.c:106
static void send_ruleset_goods(struct conn_list *dest)
Definition ruleset.c:8668
static const char name_too_long[]
Definition ruleset.c:115
bool reload_rulesets_settings(void)
Definition ruleset.c:9569
static struct strvec * lookup_strvec(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleset.c:1184
#define CITYSTYLE_SECTION_PREFIX
Definition ruleset.c:88
static bool load_action_range(struct rscompat_info *compat, struct section_file *file, action_id act)
Definition ruleset.c:6370
static bool lookup_tech(struct section_file *file, struct advance **result, const char *prefix, const char *entry, const char *filename, const char *description)
Definition ruleset.c:867
static bool load_game_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1363
static void send_ruleset_specialists(struct conn_list *dest)
Definition ruleset.c:8194
static bool load_ruleset_veteran(struct section_file *file, const char *path, struct veteran_system **vsystem, char *err, size_t err_len, struct rscompat_info *compat)
Definition ruleset.c:1943
#define ADVANCE_SECTION_PREFIX
Definition ruleset.c:85
#define EFFECT_SECTION_PREFIX
Definition ruleset.c:90
static void send_ruleset_action_auto_performers(struct conn_list *dest)
Definition ruleset.c:8809
static bool load_government_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:4355
static void send_ruleset_team_names(struct conn_list *dest)
Definition ruleset.c:9216
static void send_ruleset_cities(struct conn_list *dest)
Definition ruleset.c:9101
static bool lookup_building(struct section_file *file, const char *prefix, const char *entry, struct impr_type **result, const char *filename, const char *description)
Definition ruleset.c:899
static bool purge_redundant_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleset.c:403
static char * lookup_string(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleset.c:1164
static const char * check_leader_names(struct nation_type *pnation)
Definition ruleset.c:4668
#define ACTION_ENABLER_SECTION_PREFIX
Definition ruleset.c:108
#define BASE_SECTION_PREFIX
Definition ruleset.c:98
static int ruleset_purge_redundant_reqs_effects(void)
Definition ruleset.c:452
static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir, char **buffer, bool optional)
Definition ruleset.c:590
char * get_parser_buffer(void)
Definition ruleset.c:553
static bool load_building_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2640
#define EXTRA_SECTION_PREFIX
Definition ruleset.c:97
static bool load_action_range_max(struct rscompat_info *compat, struct section_file *file, action_id act)
Definition ruleset.c:6319
void send_rulesets(struct conn_list *dest)
Definition ruleset.c:9592
#define CLAUSE_SECTION_PREFIX
Definition ruleset.c:96
static bool lookup_unit_list(struct section_file *file, const char *prefix, const char *entry, struct unit_type **output, const char *filename)
Definition ruleset.c:932
static char * resource_sections
Definition ruleset.c:119
#define UNIT_SECTION_PREFIX
Definition ruleset.c:105
#define ACHIEVEMENT_SECTION_PREFIX
Definition ruleset.c:107
static bool load_ruleset_cities(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5956
static bool load_ruleset_styles(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5777
static struct government * lookup_government(struct section_file *file, const char *entry, const char *filename, struct government *fallback)
Definition ruleset.c:1139
static bool load_ruleset_units(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:2075
char * script_buffer
Definition ruleset.c:199
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 ruleset.c:1275
static bool load_action_blocked_by_list(struct section_file *file, const char *filename, struct action *paction)
Definition ruleset.c:6435
static void send_ruleset_styles(struct conn_list *dest)
Definition ruleset.c:9019
#define NATION_GROUP_SECTION_PREFIX
Definition ruleset.c:93
static char * extra_sections
Definition ruleset.c:121
#define RULES_SUFFIX
Definition ruleset.c:82
struct requirement_vector * lookup_req_list(struct section_file *file, struct rscompat_info *compat, const char *sec, const char *sub, const char *rfor)
Definition ruleset.c:645
static void send_ruleset_disasters(struct conn_list *dest)
Definition ruleset.c:8700
static bool purge_duplicate_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleset.c:358
static bool lookup_tech_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleset.c:992
#define MAX_SECTION_LABEL
Definition ruleset.c:116
#define BUILDING_SECTION_PREFIX
Definition ruleset.c:87
static bool load_ruleset_game(struct section_file *file, bool act, struct rscompat_info *compat)
Definition ruleset.c:6550
static bool load_nation_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:4688
static void send_ruleset_achievements(struct conn_list *dest)
Definition ruleset.c:8730
#define SCRIPT_SUFFIX
Definition ruleset.c:83
static void send_ruleset_bases(struct conn_list *dest)
Definition ruleset.c:8606
static bool load_ruleset_terrain(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:3143
static int ruleset_purge_unused_effects(void)
Definition ruleset.c:281
static bool load_action_actor_consuming_always(struct section_file *file, action_id act)
Definition ruleset.c:6418
static bool load_action_post_success_force(struct section_file *file, const char *filename, int performer_slot, struct action *paction)
Definition ruleset.c:6479
static bool load_tech_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1456
#define SPECIALIST_SECTION_PREFIX
Definition ruleset.c:102
static bool lookup_cbonus_list(struct rscompat_info *compat, struct combat_bonus_list *list, struct section_file *file, const char *sec, const char *sub)
Definition ruleset.c:805
static bool load_action_kind(struct section_file *file, action_id act)
Definition ruleset.c:6396
static void send_ruleset_multipliers(struct conn_list *dest)
Definition ruleset.c:9067
char * get_script_buffer(void)
Definition ruleset.c:545
static void send_ruleset_actions(struct conn_list *dest)
Definition ruleset.c:8751
static bool load_city_name_list(struct section_file *file, struct nation_type *pnation, const char *secfile_str1, const char *secfile_str2, const char **allowed_terrains, size_t atcount)
Definition ruleset.c:4843
static bool load_action_auto_uflag_block(struct section_file *file, struct action_auto_perf *auto_perf, const char *uflags_path, const char *filename)
Definition ruleset.c:5855
static bool load_ruleset_nations(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:5013
static bool load_action_auto_actions(struct section_file *file, struct action_auto_perf *auto_perf, const char *actions_path, const char *filename)
Definition ruleset.c:5898
static void send_ruleset_unit_classes(struct conn_list *dest)
Definition ruleset.c:8005
#define TECH_CLASS_SECTION_PREFIX
Definition ruleset.c:86
#define RESOURCE_SECTION_PREFIX
Definition ruleset.c:100
static bool lookup_unit_type(struct section_file *file, const char *prefix, const char *entry, const struct unit_type **result, const char *filename, const char *description)
Definition ruleset.c:1108
static void send_ruleset_extras(struct conn_list *dest)
Definition ruleset.c:8492
#define rs_sanity_veteran(_path, _entry, _i, _condition, _action)
static void send_ruleset_terrain(struct conn_list *dest)
Definition ruleset.c:8370
#define GOVERNMENT_SECTION_PREFIX
Definition ruleset.c:91
static bool load_unit_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleset.c:1784
static void send_ruleset_trade_routes(struct conn_list *dest)
Definition ruleset.c:8845
static void notify_ruleset_fallback(const char *msg)
Definition ruleset.c:9238
static bool lookup_bv_actions(struct section_file *file, const char *filename, bv_actions *target, const char *path)
Definition ruleset.c:6516
static void send_ruleset_buildings(struct conn_list *dest)
Definition ruleset.c:8332
#define UNIT_CLASS_SECTION_PREFIX
Definition ruleset.c:104
static bool ruleset_load_names(struct name_translation *pname, const char *domain, struct section_file *file, const char *sec_name)
Definition ruleset.c:1301
#define ROAD_SECTION_PREFIX
Definition ruleset.c:99
static const char * valid_ruleset_filename(const char *subdir, const char *name, const char *extension, bool optional)
Definition ruleset.c:500
static bool load_muuk_as_action_auto(struct section_file *file, struct action_auto_perf *auto_perf, const char *item, const char *filename)
Definition ruleset.c:5934
#define NATION_SET_SECTION_PREFIX
Definition ruleset.c:92
#define RS_DEFAULT_DAMAGE_REDUCES_BOMBARD_RATE
Definition ruleset.h:107
#define RS_DEFAULT_TECH_TRADE_LOSS_HOLES
Definition ruleset.h:84
#define RS_DEFAULT_TECH_COST_STYLE
Definition ruleset.h:90
#define RS_DEFAULT_EXTRA_APPEARANCE
Definition ruleset.h:101
#define RS_DEFAULT_TECH_PARASITE_HOLES
Definition ruleset.h:85
#define GAME_DEFAULT_ACH_VALUE
Definition ruleset.h:78
#define RS_DEFAULT_TECH_TRADE_HOLES
Definition ruleset.h:83
#define RS_DEFAULT_CULTURE_VIC_POINTS
Definition ruleset.h:94
#define RS_DEFAULT_CULTURE_MIGRATION_PML
Definition ruleset.h:96
void(* rs_conversion_logger)(const char *msg)
Definition ruleset.h:40
#define RS_DEFAULT_SMALL_WONDER_VISIBILITY
Definition ruleset.h:109
#define ruleset_error(logger, level, format,...)
Definition ruleset.h:57
#define RS_DEFAULT_ONLY_KILLING_VETERAN
Definition ruleset.h:104
#define RS_DEFAULT_TECH_LOSS_HOLES
Definition ruleset.h:86
#define RS_DEFAULT_HISTORY_INTEREST_PML
Definition ruleset.h:97
#define RS_DEFAULT_TECH_UPKEEP_STYLE
Definition ruleset.h:92
#define RS_DEFAULT_GOODS_SELECTION
Definition ruleset.h:99
#define RS_DEFAULT_PYTHAGOREAN_DIAGONAL
Definition ruleset.h:87
#define RS_DEFAULT_TECH_STEAL_HOLES
Definition ruleset.h:82
#define GAME_DEFAULT_ACH_UNIQUE
Definition ruleset.h:77
#define RS_DEFAULT_COMBAT_ODDS_SCALED_VETERANCY
Definition ruleset.h:106
#define RS_DEFAULT_MUUK_FOOD_WIPE
Definition ruleset.h:79
#define RS_DEFAULT_MUUK_GOLD_WIPE
Definition ruleset.h:80
#define GAME_DEFAULT_CHANGABLE_TAX
Definition ruleset.h:72
#define RS_DEFAULT_MUUK_SHIELD_WIPE
Definition ruleset.h:81
#define RS_DEFAULT_GOLD_UPKEEP_STYLE
Definition ruleset.h:89
#define GAME_DEFAULT_NATIONALITY
Definition ruleset.h:74
#define GAME_DEFAULT_ADDTOSIZE
Definition ruleset.h:71
#define RS_DEFAULT_ONLY_REAL_FIGHT_VETERAN
Definition ruleset.h:105
#define RS_DEFAULT_EXTRA_DISAPPEARANCE
Definition ruleset.h:102
#define GAME_DEFAULT_VISION_REVEAL_TILES
Definition ruleset.h:73
#define RS_DEFAULT_CULTURE_VIC_LEAD
Definition ruleset.h:95
#define RS_DEFAULT_TECH_LEAKAGE
Definition ruleset.h:91
#define RSFORMAT_3_1
Definition ruleset.h:36
#define GAME_DEFAULT_DISASTER_FREQ
Definition ruleset.h:76
#define GAME_DEFAULT_CONVERT_SPEED
Definition ruleset.h:75
static struct compatibility compat[]
Definition savecompat.c:101
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)
bool settings_ruleset(struct section_file *file, const char *section, bool act)
Definition settings.c:4178
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:183
bool check_strlen(const char *str, size_t len, const char *errmsg)
Definition shared.c:492
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1094
void remove_leading_trailing_spaces(char *s)
Definition shared.c:443
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:2395
void update_nations_with_startpos(void)
Definition srv_main.c:2200
void strvec_store(struct strvec *psv, const char *const *vec, size_t size)
struct strvec * strvec_new(void)
struct requirement_vector reqs
Definition actions.h:574
enum action_auto_perf_cause cause
Definition actions.h:570
action_id alternatives[MAX_NUM_ACTIONS]
Definition actions.h:578
action_id action
Definition actions.h:439
struct requirement_vector actor_reqs
Definition actions.h:440
struct requirement_vector target_reqs
Definition actions.h:441
action_id id
Definition actions.h:380
bool actor_consuming_always
Definition actions.h:412
int max_distance
Definition actions.h:395
bool quiet
Definition actions.h:402
enum action_result result
Definition actions.h:382
char ui_name[MAX_LEN_NAME]
Definition actions.h:398
bv_action_sub_results sub_results
Definition actions.h:383
enum action_actor_kind actor_kind
Definition actions.h:385
bv_actions blocked_by
Definition actions.h:406
enum action_target_kind target_kind
Definition actions.h:386
int min_distance
Definition actions.h:395
struct advance * require[AR_SIZE]
Definition tech.h:132
int border_sq
Definition base.h:44
int vision_main_sq
Definition base.h:45
enum base_gui_type gui_type
Definition base.h:43
int vision_invis_sq
Definition base.h:46
int vision_subs_sq
Definition base.h:47
char citizens_graphic[MAX_LEN_NAME]
Definition city.h:475
char graphic_alt[MAX_LEN_NAME]
Definition city.h:474
char graphic[MAX_LEN_NAME]
Definition city.h:473
struct civ_game::@29 rgame
char * nationlist
Definition game.h:274
int named_teams
Definition game.h:286
size_t as_count
Definition game.h:285
const char ** allowed_govs
Definition game.h:277
int upgrade_veteran_loss
Definition game.h:198
struct rgbcolor * plr_bg_color
Definition game.h:102
int incite_total_factor
Definition game.h:149
int init_vis_radius_sq
Definition game.h:151
struct civ_game::@30::@34 server
bool vision_reveal_tiles
Definition game.h:199
char * description_file
Definition game.h:273
struct packet_ruleset_control control
Definition game.h:83
char * ruleset_summary
Definition game.h:84
char ** nc_agovs
Definition game.h:278
int base_incite_cost
Definition game.h:133
int global_init_techs[MAX_NUM_TECH_LIST]
Definition game.h:107
struct packet_game_info info
Definition game.h:89
int autoupgrade_veteran_loss
Definition game.h:131
char rulesetdir[MAX_LEN_NAME]
Definition game.h:236
int start_year
Definition game.h:190
int incite_improvement_factor
Definition game.h:148
struct section_file * luadata
Definition game.h:244
char ** embedded_nations
Definition game.h:275
int global_init_buildings[MAX_NUM_BUILDING_LIST]
Definition game.h:108
struct civ_game::@30::@34::@39 ruledit
struct trait_limits default_traits[TRAIT_COUNT]
Definition game.h:270
char ** nc_astyles
Definition game.h:284
const char ** allowed_terrains
Definition game.h:280
char * ruleset_description
Definition game.h:85
size_t ag_count
Definition game.h:279
const char ** allowed_styles
Definition game.h:283
char ** nc_aterrs
Definition game.h:281
size_t embedded_nations_count
Definition game.h:276
int incite_unit_factor
Definition game.h:150
char * ruleset_capabilities
Definition game.h:86
int ransom_gold
Definition game.h:174
size_t at_count
Definition game.h:282
struct veteran_system * veteran
Definition game.h:100
struct packet_calendar_info calendar
Definition game.h:90
struct government * default_government
Definition game.h:93
struct government * government_during_revolution
Definition game.h:94
struct civ_map::@41::@43 server
bool ocean_resources
Definition map_types.h:105
struct requirement_vector receiver_reqs
Definition diptreaty.h:57
struct requirement_vector giver_reqs
Definition diptreaty.h:56
bool enabled
Definition diptreaty.h:55
enum unit_type_flag_id flag
Definition unittype.h:448
enum combat_bonus_type type
Definition unittype.h:449
bv_extras conflicts
Definition extras.h:129
struct name_translation name
Definition extras.h:87
int build_cost
Definition improvement.h:77
char graphic_str[MAX_LEN_NAME]
Definition improvement.h:73
enum impr_genus_id genus
Definition improvement.h:80
char graphic_alt[MAX_LEN_NAME]
Definition improvement.h:74
struct requirement_vector obsolete_by
Definition improvement.h:76
char soundtag_alt[MAX_LEN_NAME]
Definition improvement.h:84
struct requirement_vector reqs
Definition improvement.h:75
struct strvec * helptext
Definition improvement.h:82
struct name_translation name
Definition improvement.h:70
bv_impr_flags flags
Definition improvement.h:81
char soundtag[MAX_LEN_NAME]
Definition improvement.h:83
Definition climisc.h:80
struct requirement_vector reqs
Definition style.h:33
char music_peaceful[MAX_LEN_NAME]
Definition style.h:31
char music_combat[MAX_LEN_NAME]
Definition style.h:32
bool hidden
Definition nation.h:168
struct name_translation noun_plural
Definition nation.h:101
struct nation_list * parent_nations
Definition nation.h:135
struct name_translation adjective
Definition nation.h:100
char * legend
Definition nation.h:106
enum barbarian_type barb_type
Definition nation.h:109
struct nation_type::@50::@52 server
char positive_year_label[MAX_LEN_NAME]
char negative_year_label[MAX_LEN_NAME]
char calendar_fragment_name[MAX_CALENDAR_FRAGMENTS][MAX_LEN_NAME]
bool tech_steal_allow_holes
enum gameloss_style gameloss_style
enum goods_selection_method goods_selection
Government_type_id government_during_revolution_id
enum gold_upkeep_style gold_upkeep_style
bool damage_reduces_bombard_rate
int nuke_defender_survival_chance_pct
enum tech_upkeep_style tech_upkeep_style
bool tech_trade_loss_allow_holes
int granary_food_ini[MAX_GRANARY_INIS]
enum free_tech_method free_tech_method
bool steal_maps_reveals_all_cities
bool only_real_fight_makes_veteran
int low_firepower_pearl_harbour
enum tech_leakage_style tech_leakage
bool airlift_from_always_enabled
bool only_killing_makes_veteran
bool poison_empties_food_stock
bv_actions diplchance_initial_odds
bool tech_trade_allow_holes
int low_firepower_nonnat_bombard
bool tech_parasite_allow_holes
int low_firepower_combat_bonus
int border_city_permanent_radius_sq
int low_firepower_badwallattacker
bool airlift_to_always_enabled
enum wonder_visib_type small_wonder_visibility
enum tech_cost_style tech_cost_style
bool combat_odds_scaled_veterancy
int civil_war_bonus_celebrating
Government_type_id default_government_id
int min_city_center_output[O_LAST]
char rule_name[MAX_LEN_NAME]
enum achievement_type type
char name[MAX_LEN_NAME]
action_id alternatives[MAX_NUM_ACTIONS]
struct requirement reqs[MAX_NUM_REQS]
enum action_auto_perf_cause cause
struct requirement actor_reqs[MAX_NUM_REQS]
struct requirement target_reqs[MAX_NUM_REQS]
enum action_sub_target_kind sub_tgt_kind
enum action_actor_kind act_kind
bv_action_sub_results sub_results
char ui_name[MAX_LEN_NAME]
enum action_target_kind tgt_kind
enum action_result result
enum base_gui_type gui_type
char helptext[MAX_LEN_PACKET]
struct requirement obs_reqs[MAX_NUM_REQS]
char soundtag_alt[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
enum impr_genus_id genus
char name[MAX_LEN_NAME]
char soundtag[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
char citizens_graphic[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
char graphic[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
enum clause_type type
struct requirement receiver_reqs[MAX_NUM_REQS]
struct requirement giver_reqs[MAX_NUM_REQS]
char preferred_soundset[MAX_LEN_NAME]
char version[MAX_LEN_NAME]
char preferred_tileset[MAX_LEN_NAME]
char alt_dir[MAX_LEN_NAME]
char preferred_musicset[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
bv_disaster_effects effects
char name[MAX_LEN_NAME]
char helptxt[MAX_LEN_PACKET]
char name[MAX_LEN_NAME]
bv_unit_classes native_to
struct requirement reqs[MAX_NUM_REQS]
char graphic_alt[MAX_LEN_NAME]
char act_gfx_alt2[MAX_LEN_NAME]
struct requirement disappearance_reqs[MAX_NUM_REQS]
bv_extra_flags flags
char act_gfx_alt[MAX_LEN_NAME]
char activity_gfx[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
enum extra_unit_seen_type eus
struct requirement appearance_reqs[MAX_NUM_REQS]
char name[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
char rmact_gfx_alt[MAX_LEN_NAME]
char rmact_gfx[MAX_LEN_NAME]
struct requirement rmreqs[MAX_NUM_REQS]
char helptext[MAX_LEN_PACKET]
int work_raise_chance[MAX_VET_LEVELS]
int base_raise_chance[MAX_VET_LEVELS]
int global_init_techs[MAX_NUM_TECH_LIST]
int move_bonus[MAX_VET_LEVELS]
char veteran_name[MAX_VET_LEVELS][MAX_LEN_NAME]
Impr_type_id global_init_buildings[MAX_NUM_BUILDING_LIST]
int power_fact[MAX_VET_LEVELS]
char helptext[MAX_LEN_PACKET]
bv_goods_flags flags
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
char name[MAX_LEN_NAME]
Multiplier_type_id id
struct requirement reqs[MAX_NUM_REQS]
char rule_name[MAX_LEN_NAME]
char helptext[MAX_LEN_PACKET]
char music_combat[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
char music_peaceful[MAX_LEN_NAME]
char groups[MAX_NUM_NATION_GROUPS][MAX_LEN_NAME]
bool hidden[MAX_NUM_NATION_GROUPS]
char rule_names[MAX_NUM_NATION_SETS][MAX_LEN_NAME]
char names[MAX_NUM_NATION_SETS][MAX_LEN_NAME]
char descriptions[MAX_NUM_NATION_SETS][MAX_LEN_MSG]
int init_techs[MAX_NUM_TECH_LIST]
char leader_name[MAX_NUM_LEADERS][MAX_LEN_NAME]
char noun_plural[MAX_LEN_NAME]
char adjective[MAX_LEN_NAME]
Impr_type_id init_buildings[MAX_NUM_BUILDING_LIST]
Unit_type_id init_units[MAX_NUM_UNIT_LIST]
bool leader_is_male[MAX_NUM_LEADERS]
char translation_domain[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
Government_type_id init_government_id
int groups[MAX_NUM_NATION_GROUPS]
enum barbarian_type barbarian_type
int sets[MAX_NUM_NATION_SETS]
char graphic_alt[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char legend[MAX_LEN_MSG]
bv_road_flags flags
int tile_incr_const[O_LAST]
enum road_gui_type gui_type
bv_max_extras integrates
enum road_compat compat
enum road_move_mode move_mode
int tile_bonus[O_LAST]
int tile_incr[O_LAST]
struct requirement first_reqs[MAX_NUM_REQS]
char rule_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
struct requirement reqs[MAX_NUM_REQS]
Specialist_type_id id
char helptext[MAX_LEN_PACKET]
char short_name[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
char plural_name[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char text[MAX_LEN_CONTENT]
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char helptxt[MAX_LEN_PACKET]
char name[MAX_LEN_NAME]
struct requirement research_reqs[MAX_NUM_REQS]
char graphic_str[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
bv_tech_flags flags
char helptext[MAX_LEN_PACKET]
char name[MAX_LEN_NAME]
char helptxt[MAX_LEN_PACKET]
Terrain_type_id transform_result
char helptext[MAX_LEN_PACKET]
bv_terrain_flags flags
Resource_type_id resources[MAX_RESOURCE_TYPES]
char graphic_str[MAX_LEN_NAME]
bv_unit_classes native_to
Terrain_type_id cultivate_result
Terrain_type_id plant_result
char name[MAX_LEN_NAME]
int road_output_incr_pct[O_LAST]
char graphic_alt[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
enum trade_route_illegal_cancelling cancelling
enum trade_route_bonus_type bonus_type
enum combat_bonus_type type
enum unit_type_flag_id flag
char helptxt[MAX_LEN_PACKET]
char rule_name[MAX_LEN_NAME]
bv_unit_class_flags flags
char name[MAX_LEN_NAME]
char helptext[MAX_LEN_PACKET]
char 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_str[MAX_LEN_NAME]
char sound_fight_alt[MAX_LEN_NAME]
bv_unit_classes disembarks
bv_unit_classes cargo
bv_unit_type_flags flags
char sound_move_alt[MAX_LEN_NAME]
bv_unit_classes targets
struct requirement build_reqs[MAX_NUM_REQS]
int base_raise_chance[MAX_VET_LEVELS]
int work_raise_chance[MAX_VET_LEVELS]
char sound_fight[MAX_LEN_NAME]
bv_unit_classes embarks
char veteran_name[MAX_VET_LEVELS][MAX_LEN_NAME]
char sound_move[MAX_LEN_NAME]
char helptext[MAX_LEN_PACKET]
bv_unit_type_roles roles
int move_bonus[MAX_VET_LEVELS]
char team_name[MAX_LEN_NAME]
Definition goto.c:52
enum req_vec_change_operation operation
struct requirement req
struct req_vec_change * suggested_solutions
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:84
struct requirement_vector first_reqs
Definition road.h:86
enum road_move_mode move_mode
Definition road.h:79
int tile_bonus[O_LAST]
Definition road.h:82
int tile_incr_const[O_LAST]
Definition road.h:80
int tile_incr[O_LAST]
Definition road.h:81
bv_road_flags flags
Definition road.h:89
int move_cost
Definition road.h:78
enum road_compat compat
Definition road.h:83
bv_max_extras integrates
Definition road.h:88
bool compat_mode
Definition rscompat.h:30
rs_conversion_logger log_cb
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:758
int base_raise_chance
Definition unittype.h:471
struct name_translation name
Definition unittype.h:468
int work_raise_chance
Definition unittype.h:472
struct veteran_level * definitions
Definition unittype.h:478
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:969
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:787
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
bool fc_isspace(char c)
Definition support.c:1249
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:832
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:896
char fc_tolower(char c)
Definition support.c:1282
#define sz_strlcpy(dest, src)
Definition support.h:161
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:121
#define fc__attribute(x)
Definition support.h:89
#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:75
#define team_slots_iterate(_tslot)
Definition team.h:70
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
const char * tech_flag_id_name_cb(enum tech_flag_id flag)
Definition tech.c:423
void set_user_tech_flag_name(enum tech_flag_id id, const char *name, const char *helptxt)
Definition tech.c:394
struct advance * valid_advance(struct advance *padvance)
Definition tech.c:152
void techs_precalc_data(void)
Definition tech.c:225
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
const char * tech_flag_helptxt(enum tech_flag_id id)
Definition tech.c:435
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
struct tech_class * tech_class_by_rule_name(const char *name)
Definition tech.c:351
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define tech_class_index(_ptclass_)
Definition tech.h:193
#define A_NEVER
Definition tech.h:51
#define tech_class_iterate_end
Definition tech.h:204
#define MAX_NUM_USER_TECH_FLAGS
Definition tech.h:108
@ AR_TWO
Definition tech.h:112
@ AR_ROOT
Definition tech.h:113
@ AR_ONE
Definition tech.h:111
#define advance_iterate(_start, _p)
Definition tech.h:264
static Tech_type_id advance_count(void)
Definition tech.h:170
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define tech_class_iterate(_p)
Definition tech.h:198
#define advance_iterate_end
Definition tech.h:270
#define A_LAST
Definition tech.h:45
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:174
Terrain_type_id terrain_count(void)
Definition terrain.c:106
const char * terrain_flag_id_name_cb(enum terrain_flag_id flag)
Definition terrain.c:805
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:126
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:144
const char * terrain_flag_helptxt(enum terrain_flag_id id)
Definition terrain.c:817
struct resource_type * resource_type_init(struct extra_type *pextra)
Definition terrain.c:260
void set_user_terrain_flag_name(enum terrain_flag_id id, const char *name, const char *helptxt)
Definition terrain.c:776
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:135
#define terrain_type_iterate(_p)
Definition terrain.h:358
#define MAX_RESOURCE_TYPES
Definition terrain.h:67
#define T_NONE
Definition terrain.h:56
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:188
#define terrain_type_iterate_end
Definition terrain.h:364
#define RESOURCE_NONE_IDENTIFIER
Definition terrain.h:47
#define RESOURCE_NULL_IDENTIFIER
Definition terrain.h:46
#define MAX_NUM_TERRAINS
Definition terrain.h:64
#define T_FIRST
Definition terrain.h:60
#define MAX_NUM_USER_TER_FLAGS
Definition terrain.h:146
#define ACTIVITY_FACTOR
Definition tile.h:164
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:2758
const char * unit_class_flag_helptxt(enum unit_class_flag_id id)
Definition unittype.c:1906
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1819
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:193
void unit_type_action_cache_init(void)
Definition unittype.c:983
void set_unit_type_caches(struct unit_type *ptype)
Definition unittype.c:2817
void role_unit_precalcs(void)
Definition unittype.c:2223
void veteran_system_definition(struct veteran_system *vsystem, int level, const char *vlist_name, int vlist_power, int vlist_move, int vlist_raise, int vlist_wraise)
Definition unittype.c:2719
Unit_type_id utype_count(void)
Definition unittype.c:80
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2661
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1630
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2631
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1693
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:1836
const char * unit_type_flag_helptxt(enum unit_type_flag_id id)
Definition unittype.c:1969
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:1864
struct veteran_system * veteran_system_new(int count)
Definition unittype.c:2688
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2515
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:443
void set_user_unit_type_flag_name(enum unit_type_flag_id id, const char *name, const char *helptxt)
Definition unittype.c:1928
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:753
#define utype_class(_t_)
Definition unittype.h:736
#define combat_bonus_list_iterate_end
Definition unittype.h:463
#define L_FIRST
Definition unittype.h:333
#define combat_bonus_list_iterate(bonuslist, pbonus)
Definition unittype.h:461
@ HUT_FRIGHTEN
Definition unittype.h:129
@ HUT_NOTHING
Definition unittype.h:129
@ HUT_NORMAL
Definition unittype.h:129
#define unit_class_iterate(_p)
Definition unittype.h:876
#define MAX_NUM_USER_UNIT_FLAGS
Definition unittype.h:316
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:604
#define UTYF_LAST_USER_FLAG
Definition unittype.h:315
#define unit_type_iterate(_p)
Definition unittype.h:838
#define U_LAST
Definition unittype.h:40
#define uclass_index(_c_)
Definition unittype.h:729
#define unit_class_iterate_end
Definition unittype.h:883
#define unit_type_iterate_end
Definition unittype.h:845
#define MAX_NUM_USER_UCLASS_FLAGS
Definition unittype.h:113