741
828
**************************************************************************/
742
829
static void load_ruleset_techs(struct section_file *file)
831
struct section_list *sec;
745
832
int num_techs; /* number of techs in the ruleset (means without A_NONE)*/
747
834
struct advance *a_none = advance_by_number(A_NONE);
748
const char *filename = secfile_filename(file);
835
const char *filename = secfile_name(file);
750
(void) check_ruleset_capabilities(file, "+1.9", filename);
751
sec = secfile_get_secnames_prefix(file, ADVANCE_SECTION_PREFIX, &num_techs);
837
(void) check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
838
sec = secfile_sections_by_name_prefix(file, ADVANCE_SECTION_PREFIX);
839
num_techs = section_list_size(sec);
753
841
/* Initialize dummy tech A_NONE */
754
842
a_none->require[AR_ONE] = a_none;
755
843
a_none->require[AR_TWO] = a_none;
756
844
a_none->require[AR_ROOT] = A_NEVER;
845
BV_CLR_ALL(a_none->flags);
760
848
advance_iterate(A_FIRST, a) {
849
const char *sec_name = section_name(section_list_get(sec, i));
850
const char *sval, **slist;
764
a->require[AR_ONE] = lookup_tech(file, sec[i], "req1", LOG_ERROR,
765
filename, a->name.vernacular);
766
a->require[AR_TWO] = lookup_tech(file, sec[i], "req2", LOG_ERROR,
767
filename, a->name.vernacular);
768
a->require[AR_ROOT] = lookup_tech(file, sec[i], "root_req", LOG_ERROR,
769
filename, a->name.vernacular);
854
a->require[AR_ONE] = lookup_tech(file, sec_name, "req1", LOG_ERROR,
855
filename, rule_name(&a->name));
856
a->require[AR_TWO] = lookup_tech(file, sec_name, "req2", LOG_ERROR,
857
filename, rule_name(&a->name));
858
a->require[AR_ROOT] = lookup_tech(file, sec_name, "root_req", LOG_ERROR,
859
filename, rule_name(&a->name));
771
861
if ((A_NEVER == a->require[AR_ONE] && A_NEVER != a->require[AR_TWO])
772
862
|| (A_NEVER != a->require[AR_ONE] && A_NEVER == a->require[AR_TWO])) {
773
freelog(LOG_ERROR, "\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
863
log_error("\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
864
filename, sec_name, rule_name(&a->name));
777
865
a->require[AR_ONE] = a->require[AR_TWO] = A_NEVER;
779
867
if (a_none == a->require[AR_ONE] && a_none != a->require[AR_TWO]) {
780
freelog(LOG_ERROR, "\"%s\" [%s] \"%s\": should have \"None\" second.",
868
log_error("\"%s\" [%s] \"%s\": should have \"None\" second.",
869
filename, sec_name, rule_name(&a->name));
784
870
a->require[AR_ONE] = a->require[AR_TWO];
785
871
a->require[AR_TWO] = a_none;
874
BV_CLR_ALL(a->flags);
790
slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec[i]);
876
slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
791
877
for(j=0; j<nval; j++) {
793
879
if(strcmp(sval,"")==0) {
796
ival = find_advance_flag_by_rule_name(sval);
798
freelog(LOG_ERROR, "\"%s\" [%s] \"%s\": bad flag name \"%s\".",
882
ival = tech_flag_id_by_name(sval, fc_strcasecmp);
883
if (!tech_flag_id_is_valid(ival)) {
884
log_error("\"%s\" [%s] \"%s\": bad flag name \"%s\".",
885
filename, sec_name, rule_name(&a->name), sval);
804
a->flags |= (1<<ival);
887
BV_SET(a->flags, ival);
809
892
sz_strlcpy(a->graphic_str,
810
secfile_lookup_str_default(file, "-", "%s.graphic", sec[i]));
893
secfile_lookup_str_default(file, "-", "%s.graphic", sec_name));
811
894
sz_strlcpy(a->graphic_alt,
812
secfile_lookup_str_default(file, "-",
813
"%s.graphic_alt", sec[i]));
815
a->helptext = lookup_helptext(file, sec[i]);
816
a->bonus_message = lookup_string(file, sec[i], "bonus_message");
895
secfile_lookup_str_default(file, "-",
896
"%s.graphic_alt", sec_name));
898
a->helptext = lookup_strvec(file, sec_name, "helptext");
899
a->bonus_message = lookup_string(file, sec_name, "bonus_message");
818
secfile_lookup_int_default(file, -1, "%s.%s", sec[i], "cost");
901
secfile_lookup_int_default(file, -1, "%s.%s", sec_name, "cost");
1207
1306
u->uclass = pclass;
1209
1308
sz_strlcpy(u->sound_move,
1210
secfile_lookup_str_default(file, "-", "%s.sound_move",
1309
secfile_lookup_str_default(file, "-", "%s.sound_move",
1212
1311
sz_strlcpy(u->sound_move_alt,
1213
secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
1312
secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
1215
1314
sz_strlcpy(u->sound_fight,
1216
secfile_lookup_str_default(file, "-", "%s.sound_fight",
1315
secfile_lookup_str_default(file, "-", "%s.sound_fight",
1218
1317
sz_strlcpy(u->sound_fight_alt,
1219
secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
1222
sz_strlcpy(u->graphic_str,
1223
secfile_lookup_str(file,"%s.graphic", sec[i]));
1318
secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
1321
if ((string = secfile_lookup_str(file, "%s.graphic", sec_name))) {
1322
sz_strlcpy(u->graphic_str, string);
1324
ruleset_error(LOG_FATAL, "%s", secfile_error());
1224
1326
sz_strlcpy(u->graphic_alt,
1225
secfile_lookup_str_default(file, "-", "%s.graphic_alt", sec[i]));
1228
secfile_lookup_int(file,"%s.build_cost", sec[i]);
1230
secfile_lookup_int(file,"%s.pop_cost", sec[i]);
1231
u->attack_strength =
1232
secfile_lookup_int(file,"%s.attack", sec[i]);
1233
u->defense_strength =
1234
secfile_lookup_int(file,"%s.defense", sec[i]);
1236
SINGLE_MOVE*secfile_lookup_int(file,"%s.move_rate", sec[i]);
1238
u->vision_radius_sq =
1239
secfile_lookup_int(file,"%s.vision_radius_sq", sec[i]);
1240
u->transport_capacity =
1241
secfile_lookup_int(file,"%s.transport_cap", sec[i]);
1242
u->hp = secfile_lookup_int(file,"%s.hitpoints", sec[i]);
1243
u->firepower = secfile_lookup_int(file,"%s.firepower", sec[i]);
1327
secfile_lookup_str_default(file, "-", "%s.graphic_alt",
1330
if (!secfile_lookup_int(file, &u->build_cost,
1331
"%s.build_cost", sec_name)
1332
|| !secfile_lookup_int(file, &u->pop_cost,
1333
"%s.pop_cost", sec_name)
1334
|| !secfile_lookup_int(file, &u->attack_strength,
1335
"%s.attack", sec_name)
1336
|| !secfile_lookup_int(file, &u->defense_strength,
1337
"%s.defense", sec_name)
1338
|| !secfile_lookup_int(file, &u->move_rate,
1339
"%s.move_rate", sec_name)
1340
|| !secfile_lookup_int(file, &u->vision_radius_sq,
1341
"%s.vision_radius_sq", sec_name)
1342
|| !secfile_lookup_int(file, &u->transport_capacity,
1343
"%s.transport_cap", sec_name)
1344
|| !secfile_lookup_int(file, &u->hp,
1345
"%s.hitpoints", sec_name)
1346
|| !secfile_lookup_int(file, &u->firepower,
1347
"%s.firepower", sec_name)
1348
|| !secfile_lookup_int(file, &u->fuel,
1349
"%s.fuel", sec_name)
1350
|| !secfile_lookup_int(file, &u->happy_cost,
1351
"%s.uk_happy", sec_name)) {
1352
ruleset_error(LOG_FATAL, "%s", secfile_error());
1354
u->move_rate *= SINGLE_MOVE;
1244
1356
if (u->firepower <= 0) {
1245
1357
ruleset_error(LOG_FATAL,
1246
1358
"\"%s\" unit_type \"%s\":"
2247
2382
**************************************************************************/
2248
2383
static void load_nation_names(struct section_file *file)
2385
struct section_list *sec;
2253
(void) section_file_lookup(file, "datafile.description"); /* unused */
2388
(void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2255
sec = secfile_get_secnames_prefix(file, NATION_SECTION_PREFIX, &game.control.nation_count);
2390
sec = secfile_sections_by_name_prefix(file, NATION_SECTION_PREFIX);
2392
ruleset_error(LOG_FATAL, "No available nations in this ruleset!");
2394
game.control.nation_count = section_list_size(sec);
2256
2395
nations_alloc(game.control.nation_count);
2258
2397
nations_iterate(pl) {
2259
2398
const int i = nation_index(pl);
2260
char *adjective = secfile_lookup_str(file, "%s.name", sec[i]);
2261
char *noun_plural = secfile_lookup_str(file, "%s.plural", sec[i]);
2399
const char *sec_name = section_name(section_list_get(sec, i));
2400
const char *noun_plural = secfile_lookup_str(file,
2401
"%s.plural", sec_name);
2263
name_strlcpy(pl->adjective.vernacular, adjective);
2264
pl->adjective.translated = NULL;
2265
name_strlcpy(pl->noun_plural.vernacular, noun_plural);
2266
pl->noun_plural.translated = NULL;
2403
ruleset_load_names(&pl->adjective, file, sec_name);
2404
name_set(&pl->noun_plural, noun_plural);
2268
2406
/* Check if nation name is already defined. */
2269
2407
for(j = 0; j < i; j++) {
2270
2408
struct nation_type *n2 = nation_by_number(j);
2272
if (0 == strcmp(n2->adjective.vernacular, pl->adjective.vernacular)
2273
|| 0 == strcmp(n2->noun_plural.vernacular, pl->noun_plural.vernacular)) {
2274
ruleset_error(LOG_FATAL,
2275
"%s nation (the %s) defined twice; "
2276
"in section nation%d and section nation%d",
2277
adjective, noun_plural, j, i);
2410
/* Compare strings after stripping off qualifiers -- we don't want
2411
* two nations to end up with identical adjectives displayed to users.
2412
* (This check only catches English, not localisations, of course.) */
2413
if (0 == strcmp(Qn_(untranslated_name(&n2->adjective)),
2414
Qn_(untranslated_name(&pl->adjective)))) {
2415
ruleset_error(LOG_FATAL,
2416
"Two nations defined with the same adjective \"%s\": "
2417
"in section \'%s\' and section \'%s\'",
2418
Qn_(untranslated_name(&pl->adjective)),
2419
section_name(section_list_get(sec, j)), sec_name);
2420
} else if (0 == strcmp(rule_name(&n2->adjective),
2421
rule_name(&pl->adjective))) {
2422
/* We cannot have the same rule name, as the game needs them to be
2424
ruleset_error(LOG_FATAL,
2425
"Two nations defined with the same rule_name \"%s\": "
2426
"in section \'%s\' and section \'%s\'",
2427
rule_name(&pl->adjective),
2428
section_name(section_list_get(sec, j)), sec_name);
2429
} else if (0 == strcmp(Qn_(untranslated_name(&n2->noun_plural)),
2430
Qn_(untranslated_name(&pl->noun_plural)))) {
2431
/* We don't want identical English plural names either. */
2432
ruleset_error(LOG_FATAL,
2433
"Two nations defined with the same plural name \"%s\": "
2434
"in section \'%s\' and section \'%s\'",
2435
Qn_(untranslated_name(&pl->noun_plural)),
2436
section_name(section_list_get(sec, j)), sec_name);
2280
2439
} nations_iterate_end;
2440
section_list_destroy(sec);
2284
/**************************************************************************
2443
/****************************************************************************
2285
2444
This function loads a city name list from a section file. The file and
2286
2445
two section names (which will be concatenated) are passed in. The
2287
2446
malloc'ed city name list (which is all filled out) will be returned.
2288
**************************************************************************/
2289
static struct nation_city* load_city_name_list(struct section_file *file,
2290
const char *secfile_str1,
2291
const char *secfile_str2)
2447
****************************************************************************/
2448
static void load_city_name_list(struct section_file *file,
2449
struct nation_type *pnation,
2450
const char *secfile_str1,
2451
const char *secfile_str2)
2294
struct nation_city *city_names;
2297
/* First we read the strings from the section file (above). */
2298
char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
2299
secfile_str1, secfile_str2);
2302
* Now we allocate enough room in the city_names array to store
2303
* all the name data. The array is NULL-terminated by
2304
* having a NULL name at the end.
2306
city_names = fc_calloc(dim + 1, sizeof(*city_names));
2307
city_names[dim].name = NULL;
2310
* Each string will be of the form
2311
* "<cityname> (<label>, <label>, ...)". The cityname is just the
2312
* name for this city, while each "label" matches a terrain type
2313
* for the city (or "river"), with a preceeding ! to negate it.
2314
* The parentheses are optional (but necessary to have the
2315
* settings, of course). Our job is now to parse this into the
2316
* nation_city structure.
2318
for (j = 0, value = 1; j < dim; j++, value++) {
2319
char *name = strchr(cities[j], '(');
2322
* Now we wish to determine values for all of the city labels.
2323
* A value of 0 means no preference (which is necessary so that
2324
* the use of this is optional); -1 means the label is negated
2325
* and 1 means it's labelled. Mostly the parsing just involves
2326
* a lot of ugly string handling...
2328
memset(city_names[j].terrain, 0,
2329
terrain_count() * sizeof(city_names[j].terrain[0]));
2330
city_names[j].river = 0;
2334
* 0-terminate the original string, then find the
2335
* close-parenthesis so that we can make sure we stop there.
2337
char *next = strchr(name + 1, ')');
2339
ruleset_error(LOG_ERROR,
2340
"\"%s\" [%s] %s: city name \"%s\" unmatched parenthesis.",
2341
secfile_filename(file),
2345
} else { /* if (!next) */
2346
name[0] = next[0] = '\0';
2349
/* Handle the labels one at a time. */
2353
next = strchr(name, ',');
2357
remove_leading_trailing_spaces(name);
2360
* The ! is used to mark a negative, which is recorded
2361
* with a -1. Otherwise we use a 1.
2363
if (name[0] == '!') {
2370
if (mystrcasecmp(name, "river") == 0) {
2371
city_names[j].river = setting;
2373
/* "handled" tracks whether we find a match (for error handling) */
2374
bool handled = FALSE;
2375
int l = strlen(name);
2377
if (l > 0 && 's' == my_tolower(name[l-1])) {
2378
/* remove frequent trailing 's' */
2382
terrain_type_iterate(pterrain) {
2383
const int i = terrain_index(pterrain);
2384
const char *isection = &terrain_sections[i * MAX_SECTION_LABEL];
2386
* Note that the section name is unique (by definition).
2387
* The sub-strings are carefully crafted for this function.
2389
if (NULL != mystrcasestr(isection, name)) {
2390
city_names[j].terrain[i] = setting;
2394
} terrain_type_iterate_end;
2396
/* Nation authors may use terrains like "lake" that are
2397
* available in the default ruleset but not in civ1/civ2.
2398
* In normal use we should just ignore hints for unknown
2399
* terrains, but nation authors may want to know about this
2400
* to spot typos etc. */
2401
ruleset_error(LOG_VERBOSE,
2402
"\"%s\" [%s] %s: terrain \"%s\" not found;"
2404
secfile_filename(file),
2410
name = next ? next + 1 : NULL;
2411
} while (name && name[0] != '\0');
2414
remove_leading_trailing_spaces(cities[j]);
2415
city_names[j].name = mystrdup(cities[j]);
2416
if (check_name(city_names[j].name)) {
2417
/* The ruleset contains a name that is too long. This shouldn't
2418
happen - if it does, the author should get immediate feedback */
2419
ruleset_error(LOG_ERROR,
2420
"\"%s\" [%s] %s: city name \"%s\" is too long;"
2422
secfile_filename(file),
2425
city_names[j].name);
2426
city_names[j].name[MAX_LEN_NAME - 1] = '\0';
2454
const char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
2455
secfile_str1, secfile_str2);
2457
/* Each string will be of the form "<cityname> (<label>, <label>, ...)".
2458
* The cityname is just the name for this city, while each "label" matches
2459
* a terrain type for the city (or "river"), with a preceeding ! to negate
2460
* it. The parentheses are optional (but necessary to have the settings,
2461
* of course). Our job is now to parse it. */
2462
for (j = 0; j < dim; j++) {
2463
size_t len = strlen(cities[j]);
2464
char city_name[len + 1], *p, *next, *end;
2465
struct nation_city *pncity;
2467
sz_strlcpy(city_name, cities[j]);
2469
/* Now we wish to determine values for all of the city labels. A value
2470
* of NCP_NONE means no preference (which is necessary so that the use
2471
* of this is optional); NCP_DISLIKE means the label is negated and
2472
* NCP_LIKE means it's labelled. Mostly the parsing just involves
2473
* a lot of ugly string handling... */
2474
if ((p = strchr(city_name, '('))) {
2477
if (!(end = strchr(p, ')'))) {
2478
ruleset_error(LOG_ERROR, "\"%s\" [%s] %s: city name \"%s\" "
2479
"unmatched parenthesis.", secfile_name(file),
2480
secfile_str1, secfile_str2, cities[j]);
2483
for (*end++ = '\0'; '\0' != *end; end++) {
2484
if (!fc_isspace(*end)) {
2485
ruleset_error(LOG_ERROR, "\"%s\" [%s] %s: city name \"%s\" "
2486
"contains characthers after last parenthesis, "
2487
"ignoring...", secfile_name(file), secfile_str1,
2488
secfile_str2, cities[j]);
2493
/* Build the nation_city. */
2494
remove_leading_trailing_spaces(city_name);
2495
if (check_name(city_name)) {
2496
/* The ruleset contains a name that is too long. This shouldn't
2497
* happen - if it does, the author should get immediate feedback. */
2498
ruleset_error(LOG_ERROR, "\"%s\" [%s] %s: city name \"%s\" "
2499
"is too long; shortening it.", secfile_name(file),
2500
secfile_str1, secfile_str2, city_name);
2501
city_name[MAX_LEN_NAME - 1] = '\0';
2503
pncity = nation_city_new(pnation, city_name);
2506
/* Handle the labels one at a time. */
2508
enum nation_city_preference prefer;
2510
if ((next = strchr(p, ','))) {
2513
remove_leading_trailing_spaces(p);
2515
/* The ! is used to mark a negative, which is recorded with
2516
* NCP_DISLIKE. Otherwise we use a NCP_LIKE.
2520
prefer = NCP_DISLIKE;
2525
if (0 == fc_strcasecmp(p, "river")) {
2526
nation_city_set_river_preference(pncity, prefer);
2528
const struct terrain *pterrain = terrain_by_rule_name(p);
2530
if (NULL == pterrain) {
2531
/* Try with removing frequent trailing 's'. */
2532
size_t l = strlen(p);
2534
if (0 < l && 's' == fc_tolower(p[l - 1])) {
2537
pterrain = terrain_by_rule_name(p);
2540
if (NULL != pterrain) {
2541
nation_city_set_terrain_preference(pncity, pterrain, prefer);
2543
/* Nation authors may use terrains like "lake" that are
2544
* available in the default ruleset but not in civ1/civ2.
2545
* In normal use we should just ignore hints for unknown
2546
* terrains, but nation authors may want to know about this
2547
* to spot typos etc. */
2548
log_verbose("\"%s\" [%s] %s: terrain \"%s\" not found;"
2550
secfile_name(file), secfile_str1, secfile_str2, p);
2554
p = next ? next + 1 : NULL;
2555
} while (NULL != p && '\0' != *p);
2559
if (NULL != cities) {
2435
2564
/**************************************************************************
2437
2566
**************************************************************************/
2438
2567
static void load_ruleset_nations(struct section_file *file)
2440
char *bad_leader, *govern;
2441
2569
struct government *gov;
2442
int dim, i, i2, j, k, nval, numgroups;
2443
2572
char temp_name[MAX_LEN_NAME];
2444
char **leaders, **sec, **civilwar_nations, **groups, **conflicts;
2574
const char *name, *bad_leader;
2446
2575
int barb_land_count = 0;
2447
2576
int barb_sea_count = 0;
2448
const char *filename = secfile_filename(file);
2450
(void) check_ruleset_capabilities(file, "+1.9", filename);
2452
groups = secfile_get_secnames_prefix(file, NATION_GROUP_SECTION_PREFIX, &numgroups);
2453
for (i = 0; i < numgroups; i++) {
2454
struct nation_group* group;
2455
name = secfile_lookup_str(file, "%s.name", groups[i]);
2456
group = add_new_nation_group(name);
2457
group->match = secfile_lookup_int(file, "%s.match", groups[i]);
2461
sec = secfile_get_secnames_prefix(file, NATION_SECTION_PREFIX, &nval);
2463
nations_iterate(pl) {
2464
const int i = nation_index(pl);
2577
const char *filename = secfile_name(file);
2578
struct section_list *sec;
2580
(void) check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
2582
sec = secfile_sections_by_name_prefix(file, NATION_GROUP_SECTION_PREFIX);
2583
section_list_iterate(sec, psection) {
2584
struct nation_group *pgroup;
2586
name = secfile_lookup_str(file, "%s.name", section_name(psection));
2588
ruleset_error(LOG_FATAL, "Error: %s", secfile_error());
2590
pgroup = nation_group_new(name);
2591
if (!secfile_lookup_int(file, &j, "%s.match", section_name(psection))) {
2592
ruleset_error(LOG_FATAL, "Error: %s", secfile_error());
2594
nation_group_set_match(pgroup, j);
2595
} section_list_iterate_end;
2596
section_list_destroy(sec);
2598
sec = secfile_sections_by_name_prefix(file, NATION_SECTION_PREFIX);
2599
nations_iterate(pnation) {
2600
struct nation_type *pconflict;
2601
const int i = nation_index(pnation);
2465
2602
char tmp[200] = "\0";
2468
groups = secfile_lookup_str_vec(file, &dim, "%s.groups", sec[i]);
2469
pl->num_groups = dim;
2470
pl->groups = fc_calloc(dim + 1, sizeof(*(pl->groups)));
2472
for (j = 0; j < dim; j++) {
2473
pl->groups[j] = find_nation_group_by_rule_name(groups[j]);
2474
if (!pl->groups[j]) {
2475
freelog(LOG_ERROR, "Nation %s: Unknown group \"%s\".",
2476
nation_rule_name(pl),
2480
pl->groups[dim] = NULL; /* extra at end of list */
2484
secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec[i]);
2485
pl->conflicts_with = fc_calloc(dim + 1, sizeof(*(pl->conflicts_with)));
2487
for (j = 0, k = 0; k < dim; j++, k++) {
2488
pl->conflicts_with[j] = find_nation_by_rule_name(conflicts[k]);
2490
if (pl->conflicts_with[j] == NO_NATION_SELECTED) {
2491
/* For nation authors, this would probably be considered an error.
2492
* But it can happen normally. The civ1 compatibility ruleset only
2493
* uses the nations that were in civ1, so not all of the links will
2496
freelog(LOG_VERBOSE,
2497
"Nation %s: conflicts_with nation \"%s\" is unknown.",
2498
nation_rule_name(pl),
2502
pl->conflicts_with[j] = NO_NATION_SELECTED; /* extra at end of list */
2505
/* nation leaders */
2507
leaders = secfile_lookup_str_vec(file, &dim, "%s.leader", sec[i]);
2508
if (dim > MAX_NUM_LEADERS) {
2509
freelog(LOG_ERROR, "Nation %s: Too many leaders; using %d of %d",
2510
nation_rule_name(pl),
2513
dim = MAX_NUM_LEADERS;
2514
} else if (dim < 1) {
2515
ruleset_error(LOG_FATAL,
2516
"Nation %s: number of leaders is %d; at least one is required.",
2517
nation_rule_name(pl),
2520
pl->leader_count = dim;
2521
pl->leaders = fc_calloc(dim /*exact*/, sizeof(*(pl->leaders)));
2523
for(j = 0; j < dim; j++) {
2524
pl->leaders[j].name = mystrdup(leaders[j]);
2525
if (check_name(leaders[j])) {
2526
pl->leaders[j].name[MAX_LEN_NAME - 1] = '\0';
2531
/* check if leader name is not already defined */
2532
if ((bad_leader = check_leader_names(i, &i2))) {
2534
ruleset_error(LOG_FATAL,
2535
"Nation %s: leader \"%s\" defined more than once.",
2536
nation_rule_name(pl),
2539
ruleset_error(LOG_FATAL,
2540
"Nations %s and %s share the same leader \"%s\".",
2541
nation_rule_name(pl),
2542
nation_rule_name(nation_by_number(i2)),
2546
/* read leaders'sexes */
2547
leaders = secfile_lookup_str_vec(file, &dim, "%s.leader_sex", sec[i]);
2548
if (dim != pl->leader_count) {
2549
ruleset_error(LOG_FATAL,
2550
"Nation %s: the leader sex count (%d) "
2551
"is not equal to the number of leaders (%d)",
2552
nation_rule_name(pl),
2556
for (j = 0; j < dim; j++) {
2557
if (0 == mystrcasecmp(leaders[j], "Male")) {
2558
pl->leaders[j].is_male = TRUE;
2559
} else if (0 == mystrcasecmp(leaders[j], "Female")) {
2560
pl->leaders[j].is_male = FALSE;
2563
"Nation %s, leader %s: sex must be either Male or Female; "
2565
nation_rule_name(pl),
2566
pl->leaders[j].name);
2567
pl->leaders[j].is_male = TRUE;
2572
pl->is_available = secfile_lookup_bool_default(file, TRUE,
2573
"%s.is_available", sec[i]);
2575
pl->is_playable = secfile_lookup_bool_default(file, TRUE,
2576
"%s.is_playable", sec[i]);
2577
if (pl->is_playable) {
2603
const char *barb_type;
2604
const char *sec_name = section_name(section_list_get(sec, i));
2606
/* Nation groups. */
2607
vec = secfile_lookup_str_vec(file, &dim, "%s.groups", sec_name);
2608
for (j = 0; j < dim; j++) {
2609
struct nation_group *pgroup = nation_group_by_rule_name(vec[j]);
2611
if (NULL != pgroup) {
2612
nation_group_list_append(pnation->groups, pgroup);
2614
/* For nation authors, this would probably be considered an error.
2615
* But it can happen normally. The civ1 compatibility ruleset only
2616
* uses the nations that were in civ1, so not all of the links will
2618
log_verbose("Nation %s: Unknown group \"%s\".",
2619
nation_rule_name(pnation), vec[j]);
2626
/* Nation conflicts. */
2627
vec = secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec_name);
2628
for (j = 0; j < dim; j++) {
2629
pconflict = nation_by_rule_name(vec[j]);
2631
if (NULL != pconflict) {
2632
nation_list_append(pnation->server.conflicts_with, pconflict);
2634
/* For nation authors, this would probably be considered an error.
2635
* But it can happen normally. The civ1 compatibility ruleset only
2636
* uses the nations that were in civ1, so not all of the links will
2638
log_verbose("Nation %s: conflicts_with nation \"%s\" is unknown.",
2639
nation_rule_name(pnation), vec[j]);
2646
/* Nation leaders. */
2647
for (j = 0; j < MAX_NUM_LEADERS; j++) {
2649
bool is_male = FALSE;
2651
name = secfile_lookup_str(file, "%s.leaders%d.name", sec_name, j);
2653
/* No more to read. */
2657
if (check_name(name)) {
2658
/* The ruleset contains a name that is too long. This shouldn't
2659
* happen - if it does, the author should get immediate feedback */
2660
sz_strlcpy(temp_name, name);
2661
ruleset_error(LOG_ERROR, "Nation %s: leader name \"%s\" "
2662
"is too long; shortening it to \"%s\".",
2663
nation_rule_name(pnation), name, temp_name);
2667
sex = secfile_lookup_str(file, "%s.leaders%d.sex", sec_name, j);
2669
ruleset_error(LOG_FATAL, "Nation %s: leader \"%s\": %s.",
2670
nation_rule_name(pnation), name, secfile_error());
2671
} else if (0 == fc_strcasecmp("Male", sex)) {
2673
} else if (0 != fc_strcasecmp("Female", sex)) {
2674
ruleset_error(LOG_FATAL, "Nation %s: leader \"%s\" has unsupported "
2675
"sex variant \"%s\".",
2676
nation_rule_name(pnation), name, sex);
2678
(void) nation_leader_new(pnation, name, is_male);
2681
/* Check the number of leaders. */
2682
if (MAX_NUM_LEADERS == j) {
2683
/* Too much leaders, get the real number defined in the ruleset. */
2684
while (NULL != secfile_entry_lookup(file, "%s.leaders%d.name",
2688
log_error("Nation %s: Too many leaders; using %d of %d",
2689
nation_rule_name(pnation), MAX_NUM_LEADERS, j);
2690
} else if (0 == j) {
2691
ruleset_error(LOG_FATAL,
2692
"Nation %s: no leaders; at least one is required.",
2693
nation_rule_name(pnation));
2696
/* Check if leader name is not already defined */
2697
if ((bad_leader = check_leader_names(pnation, &pconflict))) {
2698
if (pnation == pconflict) {
2699
ruleset_error(LOG_FATAL,
2700
"Nation %s: leader \"%s\" defined more than once.",
2701
nation_rule_name(pnation), bad_leader);
2703
ruleset_error(LOG_FATAL,
2704
"Nations %s and %s share the same leader \"%s\".",
2705
nation_rule_name(pnation), nation_rule_name(pconflict),
2710
pnation->is_available =
2711
secfile_lookup_bool_default(file, TRUE, "%s.is_available", sec_name);
2712
pnation->is_playable =
2713
secfile_lookup_bool_default(file, TRUE, "%s.is_playable", sec_name);
2715
if (pnation->is_playable) {
2578
2716
server.playable_nations++;
2581
/* Check barbarian type. Default is "None" meaning not a barbarian */
2719
/* Check barbarian type. Default is "None" meaning not a barbarian */
2582
2720
barb_type = secfile_lookup_str_default(file, "None",
2583
"%s.barbarian_type", sec[i]);
2584
if (mystrcasecmp(barb_type, "None") == 0) {
2585
pl->barb_type = NOT_A_BARBARIAN;
2586
} else if (mystrcasecmp(barb_type, "Land") == 0) {
2587
if (pl->is_playable) {
2721
"%s.barbarian_type", sec_name);
2722
if (fc_strcasecmp(barb_type, "None") == 0) {
2723
pnation->barb_type = NOT_A_BARBARIAN;
2724
} else if (fc_strcasecmp(barb_type, "Land") == 0) {
2725
if (pnation->is_playable) {
2588
2726
/* We can't allow players to use barbarian nations, barbarians
2589
2727
* may run out of nations */
2590
2728
ruleset_error(LOG_FATAL,
2591
2729
"Nation %s marked both barbarian and playable.",
2592
nation_rule_name(pl));
2730
nation_rule_name(pnation));
2594
pl->barb_type = LAND_BARBARIAN;
2732
pnation->barb_type = LAND_BARBARIAN;
2595
2733
barb_land_count++;
2596
} else if (mystrcasecmp(barb_type, "Sea") == 0) {
2597
if (pl->is_playable) {
2734
} else if (fc_strcasecmp(barb_type, "Sea") == 0) {
2735
if (pnation->is_playable) {
2598
2736
/* We can't allow players to use barbarian nations, barbarians
2599
2737
* may run out of nations */
2600
2738
ruleset_error(LOG_FATAL,
2601
2739
"Nation %s marked both barbarian and playable.",
2602
nation_rule_name(pl));
2740
nation_rule_name(pnation));
2604
pl->barb_type = SEA_BARBARIAN;
2742
pnation->barb_type = SEA_BARBARIAN;
2605
2743
barb_sea_count++;
2607
2745
ruleset_error(LOG_FATAL,
2608
2746
"Nation %s, barbarian_type is \"%s\". Must be "
2609
2747
"\"None\" or \"Land\" or \"Sea\".",
2610
nation_rule_name(pl),
2748
nation_rule_name(pnation), barb_type);
2616
sz_strlcpy(pl->flag_graphic_str,
2617
secfile_lookup_str_default(file, "-", "%s.flag", sec[i]));
2618
sz_strlcpy(pl->flag_graphic_alt,
2619
secfile_lookup_str_default(file, "-", "%s.flag_alt", sec[i]));
2752
sz_strlcpy(pnation->flag_graphic_str,
2753
secfile_lookup_str_default(file, "-", "%s.flag", sec_name));
2754
sz_strlcpy(pnation->flag_graphic_alt,
2755
secfile_lookup_str_default(file, "-",
2756
"%s.flag_alt", sec_name));
2621
2758
/* Ruler titles */
2624
while ((govern = secfile_lookup_str_default(file, NULL,
2625
"%s.ruler_titles%d.government",
2630
male_name = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
2632
female_name = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
2635
gov = find_government_by_rule_name(govern);
2637
struct ruler_title *title;
2639
gov->num_ruler_titles++;
2641
= fc_realloc(gov->ruler_titles,
2642
gov->num_ruler_titles * sizeof(*gov->ruler_titles));
2643
title = &(gov->ruler_titles[gov->num_ruler_titles-1]);
2647
name_strlcpy(title->male.vernacular, male_name);
2648
title->male.translated = NULL;
2650
name_strlcpy(title->female.vernacular, female_name);
2651
title->female.translated = NULL;
2760
const char *male, *female;
2762
name = secfile_lookup_str_default(file, NULL,
2763
"%s.ruler_titles%d.government",
2766
/* End of the list of ruler titles. */
2770
/* NB: even if the government doesn't exist, we load the entries for
2771
* the ruler titles to avoid warnings about unused entries. */
2772
male = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
2774
female = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
2776
gov = government_by_rule_name(name);
2779
/* log_verbose() rather than log_error() so that can use single
2780
* nation ruleset file with variety of government ruleset files: */
2781
log_verbose("Nation %s: government \"%s\" not found.",
2782
nation_rule_name(pnation), name);
2783
} else if (NULL != male && NULL != female) {
2784
(void) government_ruler_title_new(gov, pnation, male, female);
2653
/* LOG_VERBOSE rather than LOG_ERROR so that can use single nation
2654
ruleset file with variety of government ruleset files: */
2655
freelog(LOG_VERBOSE,
2656
"Nation %s: government \"%s\" not found.",
2657
nation_rule_name(pl),
2786
ruleset_error(LOG_ERROR, "%s", secfile_error());
2662
2790
/* City styles */
2664
sz_strlcpy(temp_name,
2665
secfile_lookup_str(file, "%s.city_style", sec[i]));
2666
pl->city_style = find_city_style_by_rule_name(temp_name);
2667
if (pl->city_style < 0) {
2669
"Nation %s: city style \"%s\" is unknown, using default.",
2670
nation_rule_name(pl),
2791
name = secfile_lookup_str(file, "%s.city_style", sec_name);
2792
pnation->city_style = city_style_by_rule_name(name);
2793
if (0 > pnation->city_style) {
2794
log_error("Nation %s: city style \"%s\" is unknown, using default.",
2795
nation_rule_name(pnation), name);
2796
pnation->city_style = 0;
2675
while (city_style_has_requirements(&city_styles[pl->city_style])) {
2676
if (pl->city_style == 0) {
2677
ruleset_error(LOG_FATAL,
2799
while (city_style_has_requirements(city_styles + pnation->city_style)) {
2800
if (pnation->city_style == 0) {
2801
ruleset_error(LOG_FATAL,
2678
2802
"Nation %s: the default city style is not available "
2679
"from the beginning!",
2680
nation_rule_name(pl));
2681
/* Note that we can't use temp_name here. */
2803
"from the beginning!", nation_rule_name(pnation));
2804
/* Note that we can't use temp_name here. */
2684
"Nation %s: city style \"%s\" is not available from beginning; "
2686
nation_rule_name(pl),
2806
log_error("Nation %s: city style \"%s\" is not available "
2807
"from beginning; using default.",
2808
nation_rule_name(pnation), name);
2809
pnation->city_style = 0;
2691
2812
/* Civilwar nations */
2693
civilwar_nations = secfile_lookup_str_vec(file, &dim,
2694
"%s.civilwar_nations", sec[i]);
2695
pl->civilwar_nations = fc_calloc(dim + 1, sizeof(*(pl->civilwar_nations)));
2697
for (j = 0, k = 0; k < dim; j++, k++) {
2698
pl->civilwar_nations[j] = find_nation_by_rule_name(civilwar_nations[k]);
2813
vec = secfile_lookup_str_vec(file, &dim,
2814
"%s.civilwar_nations", sec_name);
2815
for (j = 0; j < dim; j++) {
2816
pconflict = nation_by_rule_name(vec[j]);
2700
2818
/* No test for duplicate nations is performed. If there is a duplicate
2701
* entry it will just cause that nation to have an increased probability
2702
* of being chosen. */
2704
if (pl->civilwar_nations[j] == NO_NATION_SELECTED) {
2706
/* For nation authors, this would probably be considered an error.
2707
* But it can happen normally. The civ1 compatability ruleset only
2708
* uses the nations that were in civ1, so not all of the links will
2710
freelog(LOG_VERBOSE,
2711
"Nation %s: civil war nation \"%s\" is unknown.",
2712
nation_rule_name(pl),
2713
civilwar_nations[k]);
2819
* entry it will just cause that nation to have an increased
2820
* probability of being chosen. */
2821
if (NULL != pconflict) {
2822
nation_list_append(pnation->server.civilwar_nations, pconflict);
2823
nation_list_append(pconflict->server.parent_nations, pnation);
2825
/* For nation authors, this would probably be considered an error.
2826
* But it can happen normally. The civ1 compatability ruleset only
2827
* uses the nations that were in civ1, so not all of the links will
2829
log_verbose("Nation %s: civil war nation \"%s\" is unknown.",
2830
nation_rule_name(pnation), vec[j]);
2716
pl->civilwar_nations[j] = NO_NATION_SELECTED; /* end of list */
2717
free(civilwar_nations);
2719
2837
/* Load nation specific initial items */
2720
lookup_tech_list(file, sec[i], "init_techs", pl->init_techs, filename);
2721
lookup_building_list(file, sec[i], "init_buildings", pl->init_buildings,
2723
lookup_unit_list(file, sec[i], "init_units", LOG_ERROR, pl->init_units,
2725
mystrlcat(tmp, sec[i], 200);
2726
mystrlcat(tmp, ".init_government", 200);
2727
pl->init_government = lookup_government(file, tmp, filename);
2729
/* read "normal" city names */
2731
pl->city_names = load_city_name_list(file, sec[i], "cities");
2733
pl->legend = mystrdup(secfile_lookup_str(file, "%s.legend", sec[i]));
2734
if (check_strlen(pl->legend, MAX_LEN_MSG, "Legend '%s' is too long")) {
2735
pl->legend[MAX_LEN_MSG - 1] = '\0';
2838
lookup_tech_list(file, sec_name, "init_techs",
2839
pnation->server.init_techs, filename);
2840
lookup_building_list(file, sec_name, "init_buildings",
2841
pnation->server.init_buildings, filename);
2842
lookup_unit_list(file, sec_name, "init_units", LOG_ERROR,
2843
pnation->server.init_units, filename);
2844
fc_strlcat(tmp, sec_name, 200);
2845
fc_strlcat(tmp, ".init_government", 200);
2846
pnation->server.init_government = lookup_government(file, tmp, filename);
2848
/* Read default city names. */
2849
load_city_name_list(file, pnation, sec_name, "cities");
2851
pnation->legend = fc_strdup(secfile_lookup_str(file, "%s.legend",
2853
if (check_strlen(pnation->legend, MAX_LEN_MSG, NULL)) {
2854
ruleset_error(LOG_ERROR,
2855
"Nation %s: legend \"%s\" is too long;"
2856
" shortening it.", nation_rule_name(pnation),
2858
pnation->legend[MAX_LEN_MSG - 1] = '\0';
2739
} nations_iterate_end;
2741
/* Calculate parent nations. O(n^2) algorithm. */
2742
nations_iterate(pl) {
2743
struct nation_type *parents[nation_count()];
2746
nations_iterate(p2) {
2747
for (k = 0; p2->civilwar_nations[k] != NO_NATION_SELECTED; k++) {
2748
if (p2->civilwar_nations[k] == pl) {
2749
parents[count] = p2;
2753
} nations_iterate_end;
2755
assert(sizeof(parents[0]) == sizeof(*pl->parent_nations));
2756
pl->parent_nations = fc_malloc((count + 1) * sizeof(parents[0]));
2757
memcpy(pl->parent_nations, parents, count * sizeof(parents[0]));
2758
pl->parent_nations[count] = NO_NATION_SELECTED;
2759
} nations_iterate_end;
2762
section_file_check_unused(file, filename);
2763
section_file_free(file);
2861
pnation->player = NULL;
2862
} nations_iterate_end;
2864
section_list_destroy(sec);
2865
secfile_check_unused(file);
2866
secfile_destroy(file);
2765
2868
if (barb_land_count == 0) {
2766
2869
ruleset_error(LOG_FATAL,
2925
3031
**************************************************************************/
2926
3032
static void load_ruleset_effects(struct section_file *file)
3034
struct section_list *sec;
2930
3036
const char *filename;
2932
filename = secfile_filename(file);
2933
(void) check_ruleset_capabilities(file, "+1.0", filename);
2934
(void) section_file_lookup(file, "datafile.description"); /* unused */
3038
filename = secfile_name(file);
3039
(void) check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
3040
(void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2936
3042
/* Parse effects and add them to the effects ruleset cache. */
2937
sec = secfile_get_secnames_prefix(file, EFFECT_SECTION_PREFIX, &nval);
2938
for (i = 0; i < nval; i++) {
3043
sec = secfile_sections_by_name_prefix(file, EFFECT_SECTION_PREFIX);
3044
section_list_iterate(sec, psection) {
2939
3045
enum effect_type eff;
2941
3047
struct effect *peffect;
3048
const char *sec_name = section_name(psection);
2943
type = secfile_lookup_str(file, "%s.name", sec[i]);
3050
type = secfile_lookup_str(file, "%s.name", sec_name);
2945
3052
if ((eff = effect_type_from_str(type)) == EFT_LAST) {
2947
"\"%s\" [%s] lists unknown effect type \"%s\".",
2948
filename, sec[i], type);
3053
log_error("\"%s\" [%s] lists unknown effect type \"%s\".",
3054
filename, sec_name, type);
2952
value = secfile_lookup_int_default(file, 1, "%s.value", sec[i]);
3058
value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
2954
3060
peffect = effect_new(eff, value);
2956
requirement_vector_iterate(lookup_req_list(file, sec[i], "reqs", type),
3062
requirement_vector_iterate(lookup_req_list(file, sec_name, "reqs", type),
2958
3064
struct requirement *preq = fc_malloc(sizeof(*preq));
2961
3067
effect_req_append(peffect, FALSE, preq);
2962
3068
} requirement_vector_iterate_end;
2963
requirement_vector_iterate(lookup_req_list(file, sec[i], "nreqs", type),
3069
requirement_vector_iterate(lookup_req_list(file, sec_name,
2965
3072
struct requirement *preq = fc_malloc(sizeof(*preq));
2968
3075
effect_req_append(peffect, TRUE, preq);
2969
3076
} requirement_vector_iterate_end;
2973
section_file_check_unused(file, filename);
2974
section_file_free(file);
3077
} section_list_iterate_end;
3078
section_list_destroy(sec);
3080
secfile_check_unused(file);
3081
secfile_destroy(file);
3084
/**************************************************************************
3085
Print an error message if the value is out of range.
3086
**************************************************************************/
3087
static int secfile_lookup_int_default_min_max(struct section_file *file,
3088
int def, int min, int max,
3089
const char *path, ...)
3090
fc__attribute((__format__ (__printf__, 5, 6)));
3091
static int secfile_lookup_int_default_min_max(struct section_file *file,
3092
int def, int min, int max,
3093
const char *path, ...)
3099
va_start(args, path);
3100
fc_vsnprintf(fullpath, sizeof(fullpath), path, args);
3103
if (!secfile_lookup_int(file, &ival, "%s", fullpath)) {
3108
ruleset_error(LOG_ERROR,"\"%s\" should be in the interval [%d, %d] "
3109
"but is %d; using the minimal value.",
3110
fullpath, min, max, ival);
3115
ruleset_error(LOG_ERROR,"\"%s\" should be in the interval [%d, %d] "
3116
"but is %d; using the maximal value.",
3117
fullpath, min, max, ival);
2977
3124
/**************************************************************************
3020
3168
/* section: options */
3021
lookup_tech_list(&file, "options", "global_init_techs",
3169
lookup_tech_list(file, "options", "global_init_techs",
3022
3170
game.server.rgame.global_init_techs, filename);
3023
lookup_building_list(&file, "options", "global_init_buildings",
3171
lookup_building_list(file, "options", "global_init_buildings",
3024
3172
game.server.rgame.global_init_buildings, filename);
3026
3174
/* section: civstyle */
3027
3175
game.info.base_pollution
3028
= secfile_lookup_int_default(&file, RS_DEFAULT_BASE_POLLUTION,
3176
= secfile_lookup_int_default(file, RS_DEFAULT_BASE_POLLUTION,
3029
3177
"civstyle.base_pollution");
3030
3178
game.info.happy_cost
3031
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3032
RS_DEFAULT_HAPPY_COST,
3035
"civstyle.happy_cost");
3179
= secfile_lookup_int_def_min_max(file,
3180
RS_DEFAULT_HAPPY_COST,
3183
"civstyle.happy_cost");
3036
3184
game.info.food_cost
3037
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3185
= secfile_lookup_int_default_min_max(file,
3038
3186
RS_DEFAULT_FOOD_COST,
3039
3187
RS_MIN_FOOD_COST,
3040
3188
RS_MAX_FOOD_COST,
3041
3189
"civstyle.food_cost");
3042
3190
/* TODO: move to global_unit_options */
3043
game.info.base_bribe_cost
3044
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3191
game.server.base_bribe_cost
3192
= secfile_lookup_int_default_min_max(file,
3045
3193
RS_DEFAULT_BASE_BRIBE_COST,
3046
3194
RS_MIN_BASE_BRIBE_COST,
3047
3195
RS_MAX_BASE_BRIBE_COST,
3048
3196
"civstyle.base_bribe_cost");
3049
3197
/* TODO: move to global_unit_options */
3050
game.info.ransom_gold
3051
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3198
game.server.ransom_gold
3199
= secfile_lookup_int_default_min_max(file,
3052
3200
RS_DEFAULT_RANSOM_GOLD,
3053
3201
RS_MIN_RANSOM_GOLD,
3054
3202
RS_MAX_RANSOM_GOLD,
3055
3203
"civstyle.ransom_gold");
3056
3204
/* TODO: move to global_unit_options */
3057
3205
game.info.pillage_select
3058
= secfile_lookup_bool_default(&file, RS_DEFAULT_PILLAGE_SELECT,
3059
"civstyle.pillage_select");
3206
= secfile_lookup_bool_default(file, RS_DEFAULT_PILLAGE_SELECT,
3207
"civstyle.pillage_select");
3060
3208
/* TODO: move to global_unit_options */
3061
game.info.upgrade_veteran_loss
3062
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3209
game.server.upgrade_veteran_loss
3210
= secfile_lookup_int_default_min_max(file,
3063
3211
RS_DEFAULT_UPGRADE_VETERAN_LOSS,
3064
3212
RS_MIN_UPGRADE_VETERAN_LOSS,
3065
3213
RS_MAX_UPGRADE_VETERAN_LOSS,
3066
3214
"civstyle.upgrade_veteran_loss");
3067
3215
/* TODO: move to global_unit_options */
3068
game.info.autoupgrade_veteran_loss
3069
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3216
game.server.autoupgrade_veteran_loss
3217
= secfile_lookup_int_default_min_max(file,
3070
3218
RS_DEFAULT_UPGRADE_VETERAN_LOSS,
3071
3219
RS_MIN_UPGRADE_VETERAN_LOSS,
3072
3220
RS_MAX_UPGRADE_VETERAN_LOSS,
3073
3221
"civstyle.autoupgrade_veteran_loss");
3074
3222
/* TODO: move to new section research */
3075
3223
game.info.base_tech_cost
3076
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3224
= secfile_lookup_int_default_min_max(file,
3077
3225
RS_DEFAULT_BASE_TECH_COST,
3078
3226
RS_MIN_BASE_TECH_COST,
3079
3227
RS_MAX_BASE_TECH_COST,
3080
3228
"civstyle.base_tech_cost");
3082
food_ini = secfile_lookup_int_vec(&file, &game.info.granary_num_inis,
3230
food_ini = secfile_lookup_int_vec(file, (size_t *)
3231
&game.info.granary_num_inis,
3083
3232
"civstyle.granary_food_ini");
3084
3234
if (game.info.granary_num_inis > MAX_GRANARY_INIS) {
3085
3235
ruleset_error(LOG_FATAL,
3086
3236
"Too many granary_food_ini entries (%d, max %d)",
3087
3237
game.info.granary_num_inis, MAX_GRANARY_INIS);
3088
3238
} else if (game.info.granary_num_inis == 0) {
3089
freelog(LOG_ERROR, "No values for granary_food_ini. Using default "
3090
"value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
3239
log_error("No values for granary_food_ini. Using default "
3240
"value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
3091
3241
game.info.granary_num_inis = 1;
3092
3242
game.info.granary_food_ini[0] = RS_DEFAULT_GRANARY_FOOD_INI;
3161
3318
/* TODO: move to new section research */
3162
3319
game.info.tech_cost_style
3163
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3320
= secfile_lookup_int_default_min_max(file,
3164
3321
RS_DEFAULT_TECH_COST_STYLE,
3165
3322
RS_MIN_TECH_COST_STYLE,
3166
3323
RS_MAX_TECH_COST_STYLE,
3167
3324
"civstyle.tech_cost_style");
3168
3325
/* TODO: move to new section research */
3169
3326
game.info.tech_leakage
3170
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3327
= secfile_lookup_int_default_min_max(file,
3171
3328
RS_DEFAULT_TECH_LEAKAGE,
3172
3329
RS_MIN_TECH_LEAKAGE,
3173
3330
RS_MAX_TECH_LEAKAGE,
3174
3331
"civstyle.tech_leakage");
3175
3332
if (game.info.tech_cost_style == 0 && game.info.tech_leakage != 0) {
3177
"Only tech_leakage 0 supported with tech_cost_style 0.");
3178
freelog(LOG_ERROR, "Switching to tech_leakage 0.");
3333
log_error("Only tech_leakage 0 supported with tech_cost_style 0.");
3334
log_error("Switching to tech_leakage 0.");
3179
3335
game.info.tech_leakage = 0;
3182
3338
/* section: illness */
3183
3339
game.info.illness_on
3184
= secfile_lookup_bool_default(&file, RS_DEFAULT_ILLNESS_ON,
3340
= secfile_lookup_bool_default(file, RS_DEFAULT_ILLNESS_ON,
3185
3341
"illness.illness_on");
3186
3342
game.info.illness_base_factor
3187
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3343
= secfile_lookup_int_default_min_max(file,
3188
3344
RS_DEFAULT_ILLNESS_BASE_FACTOR,
3189
3345
RS_MIN_ILLNESS_BASE_FACTOR,
3190
3346
RS_MAX_ILLNESS_BASE_FACTOR,
3191
3347
"illness.illness_base_factor");
3192
3348
game.info.illness_min_size
3193
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3349
= secfile_lookup_int_default_min_max(file,
3194
3350
RS_DEFAULT_ILLNESS_MIN_SIZE,
3195
3351
RS_MIN_ILLNESS_MIN_SIZE,
3196
3352
RS_MAX_ILLNESS_MIN_SIZE,
3197
3353
"illness.illness_min_size");
3198
3354
game.info.illness_trade_infection
3199
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3355
= secfile_lookup_int_default_min_max(file,
3200
3356
RS_DEFAULT_ILLNESS_TRADE_INFECTION_PCT,
3201
3357
RS_MIN_ILLNESS_TRADE_INFECTION_PCT,
3202
3358
RS_MAX_ILLNESS_TRADE_INFECTION_PCT,
3203
3359
"illness.illness_trade_infection");
3204
3360
game.info.illness_pollution_factor
3205
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3361
= secfile_lookup_int_default_min_max(file,
3206
3362
RS_DEFAULT_ILLNESS_POLLUTION_PCT,
3207
3363
RS_MIN_ILLNESS_POLLUTION_PCT,
3208
3364
RS_MAX_ILLNESS_POLLUTION_PCT,
3209
3365
"illness.illness_pollution_factor");
3211
3367
/* section: incite_cost */
3212
game.info.base_incite_cost
3213
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3368
game.server.base_incite_cost
3369
= secfile_lookup_int_default_min_max(file,
3214
3370
RS_DEFAULT_INCITE_BASE_COST,
3215
3371
RS_MIN_INCITE_BASE_COST,
3216
3372
RS_MAX_INCITE_BASE_COST,
3217
3373
"incite_cost.base_incite_cost");
3218
game.info.incite_improvement_factor
3219
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3374
game.server.incite_improvement_factor
3375
= secfile_lookup_int_default_min_max(file,
3220
3376
RS_DEFAULT_INCITE_IMPROVEMENT_FCT,
3221
3377
RS_MIN_INCITE_IMPROVEMENT_FCT,
3222
3378
RS_MAX_INCITE_IMPROVEMENT_FCT,
3223
3379
"incite_cost.improvement_factor");
3224
game.info.incite_unit_factor
3225
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3380
game.server.incite_unit_factor
3381
= secfile_lookup_int_default_min_max(file,
3226
3382
RS_DEFAULT_INCITE_UNIT_FCT,
3227
3383
RS_MIN_INCITE_UNIT_FCT,
3228
3384
RS_MAX_INCITE_UNIT_FCT,
3229
3385
"incite_cost.unit_factor");
3230
game.info.incite_total_factor
3231
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3386
game.server.incite_total_factor
3387
= secfile_lookup_int_default_min_max(file,
3232
3388
RS_DEFAULT_INCITE_TOTAL_FCT,
3233
3389
RS_MIN_INCITE_TOTAL_FCT,
3234
3390
RS_MAX_INCITE_TOTAL_FCT,
3237
3393
/* section: global_unit_options */
3238
3394
game.info.slow_invasions
3239
= secfile_lookup_bool_default(&file, RS_DEFAULT_SLOW_INVASIONS,
3395
= secfile_lookup_bool_default(file, RS_DEFAULT_SLOW_INVASIONS,
3240
3396
"global_unit_options.slow_invasions");
3242
3398
/* section: combat_rules */
3243
3399
game.info.killstack
3244
= secfile_lookup_bool_default(&file, RS_DEFAULT_KILLSTACK,
3400
= secfile_lookup_bool_default(file, RS_DEFAULT_KILLSTACK,
3245
3401
"combat_rules.killstack");
3246
3402
game.info.tired_attack
3247
= secfile_lookup_bool_default(&file, RS_DEFAULT_TIRED_ATTACK,
3403
= secfile_lookup_bool_default(file, RS_DEFAULT_TIRED_ATTACK,
3248
3404
"combat_rules.tired_attack");
3250
3406
/* section: borders */
3251
3407
game.info.border_city_radius_sq
3252
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3408
= secfile_lookup_int_default_min_max(file,
3253
3409
RS_DEFAULT_BORDER_RADIUS_SQ_CITY,
3254
3410
RS_MIN_BORDER_RADIUS_SQ_CITY,
3255
3411
RS_MAX_BORDER_RADIUS_SQ_CITY,
3256
3412
"borders.radius_sq_city");
3257
3413
game.info.border_size_effect
3258
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3414
= secfile_lookup_int_default_min_max(file,
3259
3415
RS_DEFAULT_BORDER_SIZE_EFFECT,
3260
3416
RS_MIN_BORDER_SIZE_EFFECT,
3261
3417
RS_MAX_BORDER_SIZE_EFFECT,
3262
3418
"borders.size_effect");
3420
/* section: research */
3421
game.info.tech_upkeep_style
3422
= secfile_lookup_int_default_min_max(file,
3423
RS_DEFAULT_TECH_UPKEEP_STYLE,
3424
RS_MIN_TECH_UPKEEP_STYLE,
3425
RS_MAX_TECH_UPKEEP_STYLE,
3426
"research.tech_upkeep_style");
3427
game.info.tech_upkeep_divider
3428
= secfile_lookup_int_default_min_max(file,
3429
RS_DEFAULT_TECH_UPKEEP_DIVIDER,
3430
RS_MIN_TECH_UPKEEP_DIVIDER,
3431
RS_MAX_TECH_UPKEEP_DIVIDER,
3432
"research.tech_upkeep_divider");
3264
3434
/* section: calendar */
3265
3435
game.info.calendar_skip_0
3266
= secfile_lookup_bool_default(&file, RS_DEFAULT_CALENDAR_SKIP_0,
3436
= secfile_lookup_bool_default(file, RS_DEFAULT_CALENDAR_SKIP_0,
3267
3437
"calendar.skip_year_0");
3268
game.info.start_year
3269
= secfile_lookup_int_default(&file, GAME_START_YEAR,
3438
game.server.start_year
3439
= secfile_lookup_int_default(file, GAME_START_YEAR,
3270
3440
"calendar.start_year");
3271
3441
sz_strlcpy(game.info.positive_year_label,
3272
_(secfile_lookup_str_default(&file,
3442
_(secfile_lookup_str_default(file,
3273
3443
RS_DEFAULT_POS_YEAR_LABEL,
3274
3444
"calendar.positive_label")));
3275
3445
sz_strlcpy(game.info.negative_year_label,
3276
_(secfile_lookup_str_default(&file,
3446
_(secfile_lookup_str_default(file,
3277
3447
RS_DEFAULT_NEG_YEAR_LABEL,
3278
3448
"calendar.negative_label")));
3280
3450
/* section: teams */
3281
svec = secfile_lookup_str_vec(&file, &game.info.num_teams, "teams.names");
3282
game.info.num_teams = MIN(MAX_NUM_TEAMS, game.info.num_teams);
3283
if (game.info.num_teams <= 0) {
3284
ruleset_error(LOG_FATAL, "Missing team names in game.ruleset.");
3451
svec = secfile_lookup_str_vec(file, &teams, "teams.names");
3452
if (team_slot_count() < teams) {
3453
teams = team_slot_count();
3286
for (i = 0; i < game.info.num_teams; i++) {
3287
sz_strlcpy(game.info.team_names_orig[i], svec[i]);
3455
for (i = 0; i < teams; i++) {
3456
team_slot_set_defined_name(team_slot_by_number(i), svec[i]);
3291
section_file_check_unused(&file, filename);
3292
section_file_free(&file);
3460
settings_ruleset(file, "settings");
3462
secfile_check_unused(file);
3463
secfile_destroy(file);
3295
3466
/**************************************************************************