294
315
/**************************************************************************
295
316
Lookup a string prefix.entry in the file and return the corresponding
296
advances id. If (!required), return A_LAST if match "Never" or can't match.
297
If (required), die if can't match. Note the first tech should have
298
name "None" so that will always match.
317
advances pointer. If (!required), return A_NEVER for match "Never" or
318
can't match. If (required), die when can't match. Note the first tech
319
should have name "None" so that will always match.
299
320
If description is not NULL, it is used in the warning message
300
321
instead of prefix (eg pass unit->name instead of prefix="units2.u27")
301
322
**************************************************************************/
302
static int lookup_tech(struct section_file *file, const char *prefix,
303
const char *entry, bool required, const char *filename,
304
const char *description)
323
static struct advance *lookup_tech(struct section_file *file,
324
const char *prefix, const char *entry,
325
int loglevel, const char *filename,
326
const char *description)
329
struct advance *padvance;
309
331
sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
310
if (!sval || (!required && strcmp(sval, "Never") == 0)) {
332
if (!sval || (LOG_FATAL < loglevel && strcmp(sval, "Never") == 0)) {
313
i = find_advance_by_rule_name(sval);
315
freelog((required?LOG_FATAL:LOG_ERROR),
316
"\"%s\" %s %s: couldn't match \"%s\".",
317
filename, (description?description:prefix), entry, sval );
335
padvance = find_advance_by_rule_name(sval);
337
if (A_NEVER == padvance) {
338
ruleset_error(loglevel,
339
"\"%s\" %s %s: couldn't match \"%s\".",
340
filename, (description ? description : prefix), entry, sval);
342
/* ruleset_error returned only if error was not fatal. */
328
348
/**************************************************************************
329
349
Lookup a string prefix.entry in the file and return the corresponding
330
buildings id. If (!required), return A_LAST if match "Never" or can't match.
331
If (required), die if can't match. Note the first tech should have
332
name "None" so that will always match.
350
improvement pointer. If (!required), return B_NEVER for match "None" or
351
can't match. If (required), die when can't match.
333
352
If description is not NULL, it is used in the warning message
334
353
instead of prefix (eg pass unit->name instead of prefix="units2.u27")
335
354
**************************************************************************/
336
static int lookup_building(struct section_file *file, const char *prefix,
337
const char *entry, bool required,
338
const char *filename, const char *description)
355
static struct impr_type *lookup_building(struct section_file *file,
356
const char *prefix, const char *entry,
357
int loglevel, const char *filename,
358
const char *description)
361
struct impr_type *pimprove;
343
363
sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
344
if ((!required && !sval) || strcmp(sval, "None") == 0) {
364
if (!sval || (LOG_FATAL < loglevel && strcmp(sval, "None") == 0)) {
347
i = find_improvement_by_rule_name(sval);
349
freelog((required?LOG_FATAL:LOG_ERROR),
350
"\"%s\" %s %s: couldn't match \"%s\".",
351
filename, (description?description:prefix), entry, sval );
367
pimprove = find_improvement_by_rule_name(sval);
369
if (B_NEVER == pimprove) {
370
ruleset_error(loglevel,
371
"\"%s\" %s %s: couldn't match \"%s\".",
372
filename, (description ? description : prefix), entry, sval);
374
/* ruleset_error() returned only if error was not fatal */
362
380
/**************************************************************************
1041
1099
free(def_vblist);
1102
csec = secfile_get_secnames_prefix(file, UNIT_CLASS_SECTION_PREFIX, &nval);
1104
unit_class_iterate(ut) {
1105
int i = uclass_index(ut);
1106
char tmp[200] = "\0";
1109
mystrlcat(tmp, csec[i], 200);
1110
mystrlcat(tmp, ".move_type", 200);
1111
ut->move_type = lookup_move_type(file, tmp, filename);
1112
ut->min_speed = SINGLE_MOVE * secfile_lookup_int(file, "%s.min_speed", csec[i]);
1113
ut->hp_loss_pct = secfile_lookup_int(file,"%s.hp_loss_pct", csec[i]);
1115
hut_str = secfile_lookup_str_default(file, "Normal", "%s.hut_behavior", csec[i]);
1116
if (mystrcasecmp(hut_str, "Normal") == 0) {
1117
ut->hut_behavior = HUT_NORMAL;
1118
} else if (mystrcasecmp(hut_str, "Nothing") == 0) {
1119
ut->hut_behavior = HUT_NOTHING;
1120
} else if (mystrcasecmp(hut_str, "Frighten") == 0) {
1121
ut->hut_behavior = HUT_FRIGHTEN;
1123
ruleset_error(LOG_FATAL,
1124
"\"%s\" unit_class \"%s\":"
1125
" Illegal hut behavior \"%s\".",
1127
uclass_rule_name(ut),
1131
BV_CLR_ALL(ut->flags);
1132
slist = secfile_lookup_str_vec(file, &nval, "%s.flags", csec[i]);
1133
for(j = 0; j < nval; j++) {
1135
if(strcmp(sval,"") == 0) {
1138
ival = find_unit_class_flag_by_rule_name(sval);
1139
if (ival == UCF_LAST) {
1140
freelog(LOG_ERROR, "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
1142
uclass_rule_name(ut),
1144
ival = find_unit_flag_by_rule_name(sval);
1145
if (ival != F_LAST) {
1146
freelog(LOG_ERROR, "\"%s\" unit_class \"%s\": unit_type flag!",
1148
uclass_rule_name(ut));
1150
} else if (ut->move_type == SEA_MOVING
1151
&& ( ival == UCF_ROAD_NATIVE || ival == UCF_RIVER_NATIVE)) {
1152
freelog(LOG_ERROR, "\"%s\" unit_class \"%s\": cannot give \"%s\" flag"
1153
" to sea moving unit",
1155
uclass_rule_name(ut),
1158
BV_SET(ut->flags, ival);
1163
} unit_class_iterate_end;
1044
1165
/* Tech and Gov requirements */
1045
1166
unit_type_iterate(u) {
1046
const int i = u->index;
1167
const int i = utype_index(u);
1048
u->tech_requirement = lookup_tech(file, sec[i], "tech_req", TRUE,
1049
filename, u->name.vernacular);
1169
u->require_advance = lookup_tech(file, sec[i], "tech_req", LOG_FATAL,
1170
filename, u->name.vernacular);
1050
1171
if (section_file_lookup(file, "%s.gov_req", sec[i])) {
1051
1172
char tmp[200] = "\0";
1052
1173
mystrlcat(tmp, sec[i], 200);
1053
1174
mystrlcat(tmp, ".gov_req", 200);
1054
u->gov_requirement = lookup_government(file, tmp, filename);
1175
u->need_government = lookup_government(file, tmp, filename);
1056
u->gov_requirement = NULL; /* no requirement */
1177
u->need_government = NULL; /* no requirement */
1058
1179
} unit_type_iterate_end;
1060
1181
unit_type_iterate(u) {
1061
const int i = u->index;
1182
const int i = utype_index(u);
1063
u->obsoleted_by = lookup_unit_type(file, sec[i], "obsolete_by", FALSE,
1184
u->obsoleted_by = lookup_unit_type(file, sec[i], "obsolete_by", LOG_ERROR,
1064
1185
filename, u->name.vernacular);
1065
1186
} unit_type_iterate_end;
1067
1188
/* main stats: */
1068
1189
unit_type_iterate(u) {
1069
const int i = u->index;
1190
const int i = utype_index(u);
1070
1191
struct unit_class *pclass;
1072
u->impr_requirement = lookup_building(file, sec[i], "impr_req", FALSE,
1193
u->need_improvement = lookup_building(file, sec[i], "impr_req", LOG_ERROR,
1073
1194
filename, u->name.vernacular);
1075
1196
sval = secfile_lookup_str(file, "%s.class", sec[i]);
1076
1197
pclass = find_unit_class_by_rule_name(sval);
1078
freelog(LOG_FATAL, "\"%s\" unit_type \"%s\": bad class \"%s\".",
1199
ruleset_error(LOG_FATAL,
1200
"\"%s\" unit_type \"%s\":"
1201
" bad class \"%s\".",
1084
1206
u->uclass = pclass;
1089
u->move_type = AIR_MOVING;
1092
u->move_type = pclass->id;
1096
1208
sz_strlcpy(u->sound_move,
1097
1209
secfile_lookup_str_default(file, "-", "%s.sound_move",
1553
1772
get_output_identifier(o));
1554
1773
} output_type_iterate_end;
1556
tsec = secfile_get_secnames_prefix(file, TERRAIN_SECTION_PREFIX, &nval);
1558
1775
/* terrain details */
1560
1777
terrain_type_iterate(pterrain) {
1562
const int i = pterrain->index;
1779
const int i = terrain_index(pterrain);
1780
const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
1564
1782
sz_strlcpy(pterrain->graphic_str,
1565
secfile_lookup_str(file,"%s.graphic", tsec[i]));
1783
secfile_lookup_str(file,"%s.graphic", tsection));
1566
1784
sz_strlcpy(pterrain->graphic_alt,
1567
secfile_lookup_str(file,"%s.graphic_alt", tsec[i]));
1785
secfile_lookup_str(file,"%s.graphic_alt", tsection));
1569
1787
pterrain->identifier
1570
= secfile_lookup_str(file, "%s.identifier", tsec[i])[0];
1788
= secfile_lookup_str(file, "%s.identifier", tsection)[0];
1571
1789
if ('\0' == pterrain->identifier) {
1572
freelog(LOG_FATAL, "\"%s\" [%s] missing identifier.",
1790
ruleset_error(LOG_FATAL, "\"%s\" [%s] identifier missing value.",
1791
filename, tsection);
1576
if (UNKNOWN_TERRAIN_IDENTIFIER == pterrain->identifier) {
1577
freelog(LOG_FATAL, "\"%s\" [%s] cannot use '%c' as an identifier;"
1579
filename, tsec[i], pterrain->identifier);
1793
if (TERRAIN_UNKNOWN_IDENTIFIER == pterrain->identifier) {
1794
ruleset_error(LOG_FATAL,
1795
"\"%s\" [%s] cannot use '%c' as an identifier;"
1796
" it is reserved for unknown terrain.",
1797
filename, tsection, pterrain->identifier);
1582
1799
for (j = T_FIRST; j < i; j++) {
1583
1800
if (pterrain->identifier == terrain_by_number(j)->identifier) {
1584
freelog(LOG_FATAL, "\"%s\" [%s] has the same identifier as \"%s\".",
1587
terrain_rule_name(terrain_by_number(j)));
1801
ruleset_error(LOG_FATAL,
1802
"\"%s\" [%s] has the same identifier as [%s].",
1805
&terrain_sections[j * MAX_SECTION_LABEL]);
1592
1809
pterrain->movement_cost
1593
= secfile_lookup_int(file, "%s.movement_cost", tsec[i]);
1810
= secfile_lookup_int(file, "%s.movement_cost", tsection);
1594
1811
pterrain->defense_bonus
1595
= secfile_lookup_int(file, "%s.defense_bonus", tsec[i]);
1812
= secfile_lookup_int(file, "%s.defense_bonus", tsection);
1597
1814
output_type_iterate(o) {
1598
1815
pterrain->output[o]
1599
= secfile_lookup_int_default(file, 0, "%s.%s", tsec[i],
1816
= secfile_lookup_int_default(file, 0, "%s.%s", tsection,
1600
1817
get_output_identifier(o));
1601
1818
} output_type_iterate_end;
1603
res = secfile_lookup_str_vec (file, &nval, "%s.resources", tsec[i]);
1820
res = secfile_lookup_str_vec(file, &nval, "%s.resources", tsection);
1604
1821
pterrain->resources = fc_calloc(nval + 1, sizeof(*pterrain->resources));
1605
1822
for (j = 0; j < nval; j++) {
1606
pterrain->resources[j] = find_resource_by_rule_name(res[j]);
1607
if (!pterrain->resources[j]) {
1608
freelog(LOG_FATAL, "\"%s\" [%s] could not find resource \"%s\".",
1609
filename, tsec[i], res[j]);
1823
pterrain->resources[j] = lookup_resource(filename, res[j], tsection);
1613
1825
pterrain->resources[nval] = NULL;
1617
1829
pterrain->road_trade_incr
1618
= secfile_lookup_int(file, "%s.road_trade_incr", tsec[i]);
1619
pterrain->road_time = secfile_lookup_int(file, "%s.road_time", tsec[i]);
1830
= secfile_lookup_int(file, "%s.road_trade_incr", tsection);
1831
pterrain->road_time = secfile_lookup_int(file, "%s.road_time", tsection);
1621
1833
pterrain->irrigation_result
1622
= lookup_terrain(secfile_lookup_str(file, "%s.irrigation_result",
1623
tsec[i]), pterrain);
1834
= lookup_terrain(file, "irrigation_result", pterrain);
1624
1835
pterrain->irrigation_food_incr
1625
= secfile_lookup_int(file, "%s.irrigation_food_incr", tsec[i]);
1836
= secfile_lookup_int(file, "%s.irrigation_food_incr", tsection);
1626
1837
pterrain->irrigation_time
1627
= secfile_lookup_int(file, "%s.irrigation_time", tsec[i]);
1838
= secfile_lookup_int(file, "%s.irrigation_time", tsection);
1629
1840
pterrain->mining_result
1630
= lookup_terrain(secfile_lookup_str(file, "%s.mining_result",
1631
tsec[i]), pterrain);
1841
= lookup_terrain(file, "mining_result", pterrain);
1632
1842
pterrain->mining_shield_incr
1633
= secfile_lookup_int(file, "%s.mining_shield_incr", tsec[i]);
1843
= secfile_lookup_int(file, "%s.mining_shield_incr", tsection);
1634
1844
pterrain->mining_time
1635
= secfile_lookup_int(file, "%s.mining_time", tsec[i]);
1845
= secfile_lookup_int(file, "%s.mining_time", tsection);
1637
1847
pterrain->transform_result
1638
= lookup_terrain(secfile_lookup_str(file, "%s.transform_result",
1639
tsec[i]), pterrain);
1848
= lookup_terrain(file, "transform_result", pterrain);
1640
1849
pterrain->transform_time
1641
= secfile_lookup_int(file, "%s.transform_time", tsec[i]);
1850
= secfile_lookup_int(file, "%s.transform_time", tsection);
1642
1851
pterrain->rail_time
1643
= secfile_lookup_int_default(file, 3, "%s.rail_time", tsec[i]);
1644
pterrain->airbase_time
1645
= secfile_lookup_int_default(file, 3, "%s.airbase_time", tsec[i]);
1646
pterrain->fortress_time
1647
= secfile_lookup_int_default(file, 3, "%s.fortress_time", tsec[i]);
1852
= secfile_lookup_int_default(file, 3, "%s.rail_time", tsection);
1648
1853
pterrain->clean_pollution_time
1649
= secfile_lookup_int_default(file, 3, "%s.clean_pollution_time", tsec[i]);
1854
= secfile_lookup_int_default(file, 3, "%s.clean_pollution_time", tsection);
1650
1855
pterrain->clean_fallout_time
1651
= secfile_lookup_int_default(file, 3, "%s.clean_fallout_time", tsec[i]);
1856
= secfile_lookup_int_default(file, 3, "%s.clean_fallout_time", tsection);
1653
1858
pterrain->warmer_wetter_result
1654
= lookup_terrain(secfile_lookup_str(file, "%s.warmer_wetter_result",
1655
tsec[i]), pterrain);
1859
= lookup_terrain(file, "warmer_wetter_result", pterrain);
1656
1860
pterrain->warmer_drier_result
1657
= lookup_terrain(secfile_lookup_str(file, "%s.warmer_drier_result",
1658
tsec[i]), pterrain);
1861
= lookup_terrain(file, "warmer_drier_result", pterrain);
1659
1862
pterrain->cooler_wetter_result
1660
= lookup_terrain(secfile_lookup_str(file, "%s.cooler_wetter_result",
1661
tsec[i]), pterrain);
1863
= lookup_terrain(file, "cooler_wetter_result", pterrain);
1662
1864
pterrain->cooler_drier_result
1663
= lookup_terrain(secfile_lookup_str(file, "%s.cooler_drier_result",
1664
tsec[i]), pterrain);
1865
= lookup_terrain(file, "cooler_drier_result", pterrain);
1666
slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsec[i]);
1867
slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsection);
1667
1868
BV_CLR_ALL(pterrain->flags);
1668
1869
for (j = 0; j < nval; j++) {
1669
1870
const char *sval = slist[j];
1670
1871
enum terrain_flag_id flag = find_terrain_flag_by_rule_name(sval);
1672
1873
if (flag == TER_LAST) {
1673
freelog(LOG_FATAL, "\"%s\" [%s] has unknown flag \"%s\".",
1674
filename, tsec[i], sval);
1874
ruleset_error(LOG_FATAL, "\"%s\" [%s] has unknown flag \"%s\".",
1875
filename, tsection, sval);
1677
1877
BV_SET(pterrain->flags, flag);
1690
1890
pterrain->property[j] = secfile_lookup_int_default(file, 0,
1691
1891
"%s.property_%s",
1692
tsec[i], mg_names[j]);
1695
pterrain->helptext = lookup_helptext(file, tsec[i]);
1892
tsection, mg_names[j]);
1895
slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
1896
BV_CLR_ALL(pterrain->native_to);
1897
for (j = 0; j < nval; j++) {
1898
struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
1901
ruleset_error(LOG_FATAL,
1902
"\"%s\" [%s] is native to unknown unit class \"%s\".",
1903
filename, tsection, slist[j]);
1904
} else if (is_ocean(pterrain) && class->move_type == LAND_MOVING) {
1905
ruleset_error(LOG_FATAL,
1906
"\"%s\" oceanic [%s] is native to land units.",
1907
filename, tsection);
1908
} else if (!is_ocean(pterrain) && class->move_type == SEA_MOVING) {
1909
ruleset_error(LOG_FATAL,
1910
"\"%s\" non-oceanic [%s] is native to sea units.",
1911
filename, tsection);
1913
BV_SET(pterrain->native_to, uclass_index(class));
1918
pterrain->helptext = lookup_helptext(file, tsection);
1696
1919
} terrain_type_iterate_end;
1699
rsec = secfile_get_secnames_prefix(file, RESOURCE_SECTION_PREFIX, &nval);
1921
/* resource details */
1700
1923
resource_type_iterate(presource) {
1701
const int i = presource->index;
1924
char identifier[MAX_LEN_NAME];
1925
const int i = resource_index(presource);
1926
const char *rsection = &resource_sections[i * MAX_SECTION_LABEL];
1703
1928
output_type_iterate (o) {
1704
1929
presource->output[o] =
1705
secfile_lookup_int_default(file, 0, "%s.%s", rsec[i],
1930
secfile_lookup_int_default(file, 0, "%s.%s", rsection,
1706
1931
get_output_identifier(o));
1707
1932
} output_type_iterate_end;
1708
1933
sz_strlcpy(presource->graphic_str,
1709
secfile_lookup_str(file,"%s.graphic", rsec[i]));
1934
secfile_lookup_str(file,"%s.graphic", rsection));
1710
1935
sz_strlcpy(presource->graphic_alt,
1711
secfile_lookup_str(file,"%s.graphic_alt", rsec[i]));
1936
secfile_lookup_str(file,"%s.graphic_alt", rsection));
1713
presource->identifier
1714
= secfile_lookup_str(file, "%s.identifier", rsec[i])[0];
1715
if ('\0' == presource->identifier) {
1716
freelog(LOG_FATAL, "\"%s\" [%s] missing identifier.",
1938
sz_strlcpy(identifier,
1939
secfile_lookup_str(file,"%s.identifier", rsection));
1940
presource->identifier = identifier[0];
1720
1941
if (RESOURCE_NULL_IDENTIFIER == presource->identifier) {
1721
freelog(LOG_FATAL, "\"%s\" [%s] cannot use '%c' as an identifier;"
1723
filename, rsec[i], presource->identifier);
1942
ruleset_error(LOG_FATAL, "\"%s\" [%s] identifier missing value.",
1943
filename, rsection);
1945
if (RESOURCE_NONE_IDENTIFIER == presource->identifier) {
1946
ruleset_error(LOG_FATAL,
1947
"\"%s\" [%s] cannot use '%c' as an identifier;"
1949
filename, rsection, presource->identifier);
1726
1951
for (j = 0; j < i; j++) {
1727
1952
if (presource->identifier == resource_by_number(j)->identifier) {
1728
freelog(LOG_FATAL, "\"%s\" [%s] has the same identifier as \"%s\".",
1731
resource_rule_name(resource_by_number(j)));
1953
ruleset_error(LOG_FATAL,
1954
"\"%s\" [%s] has the same identifier as [%s].",
1957
&resource_sections[j * MAX_SECTION_LABEL]);
1735
1961
} resource_type_iterate_end;
1964
base_type_iterate(pbase) {
1965
BV_CLR_ALL(pbase->conflicts);
1966
} base_type_iterate_end;
1968
base_type_iterate(pbase) {
1969
const char *section = &base_sections[base_index(pbase) * MAX_SECTION_LABEL];
1972
struct requirement_vector *reqs;
1975
pbase->buildable = secfile_lookup_bool_default(file, TRUE,
1976
"%s.buildable", section);
1977
pbase->pillageable = secfile_lookup_bool_default(file, TRUE,
1978
"%s.pillageable", section);
1980
sz_strlcpy(pbase->graphic_str,
1981
secfile_lookup_str_default(file, "-", "%s.graphic", section));
1982
sz_strlcpy(pbase->graphic_alt,
1983
secfile_lookup_str_default(file, "-",
1984
"%s.graphic_alt", section));
1985
sz_strlcpy(pbase->activity_gfx,
1986
secfile_lookup_str_default(file, "-",
1987
"%s.activity_gfx", section));
1989
reqs = lookup_req_list(file, section, "reqs", base_rule_name(pbase));
1990
requirement_vector_copy(&pbase->reqs, reqs);
1992
slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
1993
BV_CLR_ALL(pbase->native_to);
1994
for (j = 0; j < nval; j++) {
1995
struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
1998
ruleset_error(LOG_FATAL,
1999
"\"%s\" base \"%s\" is native to unknown unit class \"%s\".",
2001
base_rule_name(pbase),
2004
BV_SET(pbase->native_to, uclass_index(class));
2009
gui_str = secfile_lookup_str(file,"%s.gui_type", section);
2010
pbase->gui_type = base_gui_type_from_str(gui_str);
2011
if (pbase->gui_type == BASE_GUI_LAST) {
2012
ruleset_error(LOG_FATAL, "\"%s\" base \"%s\": unknown gui_type \"%s\".",
2014
base_rule_name(pbase),
2018
pbase->build_time = secfile_lookup_int(file, "%s.build_time", section);
2019
pbase->border_sq = secfile_lookup_int_default(file, -1, "%s.border_sq",
2021
pbase->vision_main_sq = secfile_lookup_int_default(file, -1,
2022
"%s.vision_main_sq",
2024
pbase->vision_invis_sq = secfile_lookup_int_default(file, -1,
2025
"%s.vision_invis_sq",
2027
pbase->defense_bonus = secfile_lookup_int_default(file, 0,
2031
slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
2032
BV_CLR_ALL(pbase->flags);
2033
for (j = 0; j < nval; j++) {
2034
const char *sval = slist[j];
2035
enum base_flag_id flag = base_flag_from_str(sval);
2037
if (flag == BF_LAST) {
2038
ruleset_error(LOG_FATAL, "\"%s\" base \"%s\": unknown flag \"%s\".",
2040
base_rule_name(pbase),
2043
BV_SET(pbase->flags, flag);
2049
slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
2050
for (j = 0; j < nval; j++) {
2051
const char *sval = slist[j];
2052
struct base_type *pbase2 = find_base_type_by_rule_name(sval);
2054
if (pbase2 == NULL) {
2055
ruleset_error(LOG_FATAL, "\"%s\" base \"%s\": unknown conflict base \"%s\".",
2057
base_rule_name(pbase),
2060
BV_SET(pbase->conflicts, base_index(pbase2));
2061
BV_SET(pbase2->conflicts, base_index(pbase));
2067
if (territory_claiming_base(pbase)) {
2068
base_type_iterate(pbase2) {
2069
if (pbase2 > pbase && territory_claiming_base(pbase2)) {
2070
BV_SET(pbase->conflicts, base_index(pbase2));
2071
BV_SET(pbase2->conflicts, base_index(pbase));
2073
} base_type_iterate_end;
2076
} base_type_iterate_end;
1738
2078
section_file_check_unused(file, filename);
1739
2079
section_file_free(file);
2562
2964
const char *filename;
2567
2969
openload_ruleset_file(&file, "game");
2568
2970
filename = secfile_filename(&file);
2972
/* section: datafile */
2569
2973
(void) check_ruleset_capabilities(&file, "+1.11.1", filename);
2570
2974
(void) section_file_lookup(&file, "datafile.description"); /* unused */
2572
tileset = secfile_lookup_str_default(&file, "", "tileset.prefered");
2573
if (tileset[0] != '\0') {
2976
/* section: tileset */
2977
text = secfile_lookup_str_default(&file, "", "tileset.prefered");
2978
if (text[0] != '\0') {
2574
2979
/* There was tileset suggestion */
2575
sz_strlcpy(game.control.prefered_tileset, tileset);
2980
sz_strlcpy(game.control.prefered_tileset, text);
2577
2982
/* No tileset suggestions */
2578
2983
game.control.prefered_tileset[0] = '\0';
2581
game.info.base_pollution =
2582
secfile_lookup_int_default(&file, -20, "civstyle.base_pollution");
2583
game.info.happy_cost =
2584
secfile_lookup_int_default(&file, 2, "civstyle.happy_cost");
2585
game.info.food_cost =
2586
secfile_lookup_int_default(&file, 2, "civstyle.food_cost");
2587
game.info.base_bribe_cost =
2588
secfile_lookup_int_default(&file, 750, "civstyle.base_bribe_cost");
2589
game.info.ransom_gold =
2590
secfile_lookup_int_default(&file, 100, "civstyle.ransom_gold");
2591
game.info.base_tech_cost =
2592
secfile_lookup_int_default(&file, 20, "civstyle.base_tech_cost");
2594
output_type_iterate(o) {
2595
game.info.min_city_center_output[o]
2596
= secfile_lookup_int_default(&file, 0,
2597
"civstyle.min_city_center_%s",
2598
get_output_identifier(o));
2599
} output_type_iterate_end;
2601
/* This only takes effect if citymindist is set to 0. */
2602
game.info.min_dist_bw_cities
2603
= secfile_lookup_int(&file, "civstyle.min_dist_bw_cities");
2604
if (game.info.min_dist_bw_cities < 1) {
2605
freelog(LOG_ERROR, "Bad value %i for min_dist_bw_cities. Using 2.",
2606
game.info.min_dist_bw_cities);
2607
game.info.min_dist_bw_cities = 2;
2610
game.info.init_vis_radius_sq =
2611
secfile_lookup_int(&file, "civstyle.init_vis_radius_sq");
2613
sval = secfile_lookup_str(&file, "civstyle.hut_overflight" );
2614
if (mystrcasecmp(sval, "Nothing") == 0) {
2615
game.info.hut_overflight = OVERFLIGHT_NOTHING;
2616
} else if (mystrcasecmp(sval, "Frighten") == 0) {
2617
game.info.hut_overflight = OVERFLIGHT_FRIGHTEN;
2619
freelog(LOG_ERROR, "Bad value %s for hut_overflight. Using "
2620
"\"Frighten\".", sval);
2621
game.info.hut_overflight = OVERFLIGHT_FRIGHTEN;
2624
game.info.pillage_select =
2625
secfile_lookup_bool(&file, "civstyle.pillage_select");
2627
sval = secfile_lookup_str(&file, "civstyle.nuke_contamination" );
2628
if (mystrcasecmp(sval, "Pollution") == 0) {
2629
game.info.nuke_contamination = CONTAMINATION_POLLUTION;
2630
} else if (mystrcasecmp(sval, "Fallout") == 0) {
2631
game.info.nuke_contamination = CONTAMINATION_FALLOUT;
2633
freelog(LOG_ERROR, "Bad value %s for nuke_contamination. Using "
2634
"\"Pollution\".", sval);
2635
game.info.nuke_contamination = CONTAMINATION_POLLUTION;
2638
food_ini = secfile_lookup_int_vec(&file, &game.info.granary_num_inis,
2639
"civstyle.granary_food_ini");
2986
/* section: about */
2987
text = secfile_lookup_str(&file, "about.name");
2988
/* Ruleset/modpack name found */
2989
sz_strlcpy(game.control.name, text);
2991
text = secfile_lookup_str_default(&file, "", "about.description");
2992
if (text[0] != '\0') {
2993
/* Ruleset/modpack description found */
2994
sz_strlcpy(game.control.description, text);
2996
/* No description */
2997
game.control.description[0] = '\0';
3000
/* section: options */
3001
lookup_tech_list(&file, "options", "global_init_techs",
3002
game.server.rgame.global_init_techs, filename);
3003
lookup_building_list(&file, "options", "global_init_buildings",
3004
game.server.rgame.global_init_buildings, filename);
3006
/* section: civstyle */
3007
game.info.base_pollution
3008
= secfile_lookup_int_default(&file, RS_DEFAULT_BASE_POLLUTION,
3009
"civstyle.base_pollution");
3010
game.info.happy_cost
3011
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3012
RS_DEFAULT_HAPPY_COST,
3015
"civstyle.happy_cost");
3017
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3018
RS_DEFAULT_FOOD_COST,
3021
"civstyle.food_cost");
3022
/* TODO: move to global_unit_options */
3023
game.info.base_bribe_cost
3024
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3025
RS_DEFAULT_BASE_BRIBE_COST,
3026
RS_MIN_BASE_BRIBE_COST,
3027
RS_MAX_BASE_BRIBE_COST,
3028
"civstyle.base_bribe_cost");
3029
/* TODO: move to global_unit_options */
3030
game.info.ransom_gold
3031
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3032
RS_DEFAULT_RANSOM_GOLD,
3035
"civstyle.ransom_gold");
3036
/* TODO: move to global_unit_options */
3037
game.info.pillage_select
3038
= secfile_lookup_bool_default(&file, RS_DEFAULT_PILLAGE_SELECT,
3039
"civstyle.pillage_select");
3040
/* TODO: move to global_unit_options */
3041
game.info.upgrade_veteran_loss
3042
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3043
RS_DEFAULT_UPGRADE_VETERAN_LOSS,
3044
RS_MIN_UPGRADE_VETERAN_LOSS,
3045
RS_MAX_UPGRADE_VETERAN_LOSS,
3046
"civstyle.upgrade_veteran_loss");
3047
/* TODO: move to global_unit_options */
3048
game.info.autoupgrade_veteran_loss
3049
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3050
RS_DEFAULT_UPGRADE_VETERAN_LOSS,
3051
RS_MIN_UPGRADE_VETERAN_LOSS,
3052
RS_MAX_UPGRADE_VETERAN_LOSS,
3053
"civstyle.autoupgrade_veteran_loss");
3054
/* TODO: move to new section research */
3055
game.info.base_tech_cost
3056
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3057
RS_DEFAULT_BASE_TECH_COST,
3058
RS_MIN_BASE_TECH_COST,
3059
RS_MAX_BASE_TECH_COST,
3060
"civstyle.base_tech_cost");
3062
food_ini = secfile_lookup_int_vec(&file, &game.info.granary_num_inis,
3063
"civstyle.granary_food_ini");
2640
3064
if (game.info.granary_num_inis > MAX_GRANARY_INIS) {
2642
"Too many granary_food_ini entries; %d is the maximum!",
3065
ruleset_error(LOG_FATAL,
3066
"Too many granary_food_ini entries (%d, max %d)",
3067
game.info.granary_num_inis, MAX_GRANARY_INIS);
2645
3068
} else if (game.info.granary_num_inis == 0) {
2646
freelog(LOG_ERROR, "No values for granary_food_ini. Using 1.");
3069
freelog(LOG_ERROR, "No values for granary_food_ini. Using default "
3070
"value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
2647
3071
game.info.granary_num_inis = 1;
2648
game.info.granary_food_ini[0] = 1;
3072
game.info.granary_food_ini[0] = RS_DEFAULT_GRANARY_FOOD_INI;
2652
3076
/* check for <= 0 entries */
2653
3077
for (i = 0; i < game.info.granary_num_inis; i++) {
2654
3078
if (food_ini[i] <= 0) {
2658
food_ini[i] = food_ini[i - 1];
2660
freelog(LOG_ERROR, "Bad value for granary_food_ini[%i]. Using %i.",
3080
food_ini[i] = RS_DEFAULT_GRANARY_FOOD_INI;
3082
food_ini[i] = food_ini[i - 1];
3084
freelog(LOG_ERROR, "Bad value for granary_food_ini[%i]. Using %i.",
2663
3087
game.info.granary_food_ini[i] = food_ini[i];
2666
3090
free(food_ini);
2668
game.info.granary_food_inc =
2669
secfile_lookup_int(&file, "civstyle.granary_food_inc");
2670
if (game.info.granary_food_inc < 0) {
2671
freelog(LOG_ERROR, "Bad value %i for granary_food_inc. Using 100.",
2672
game.info.granary_food_inc);
2673
game.info.granary_food_inc = 100;
2676
game.info.tech_cost_style =
2677
secfile_lookup_int(&file, "civstyle.tech_cost_style");
2678
if (game.info.tech_cost_style < 0 || game.info.tech_cost_style > 2) {
2679
freelog(LOG_ERROR, "Bad value %i for tech_cost_style. Using 0.",
2680
game.info.tech_cost_style);
2681
game.info.tech_cost_style = 0;
2683
game.info.tech_cost_double_year =
2684
secfile_lookup_int_default(&file, 1, "civstyle.tech_cost_double_year");
2686
game.info.autoupgrade_veteran_loss
2687
= secfile_lookup_int(&file, "civstyle.autoupgrade_veteran_loss");
2689
game.info.tech_leakage =
2690
secfile_lookup_int(&file, "civstyle.tech_leakage");
2691
if (game.info.tech_leakage < 0 || game.info.tech_leakage > 3) {
2692
freelog(LOG_ERROR, "Bad value %i for tech_leakage. Using 0.",
2693
game.info.tech_leakage);
2694
game.info.tech_leakage = 0;
3092
game.info.granary_food_inc
3093
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3094
RS_DEFAULT_GRANARY_FOOD_INC,
3095
RS_MIN_GRANARY_FOOD_INC,
3096
RS_MAX_GRANARY_FOOD_INC,
3097
"civstyle.granary_food_inc");
3099
output_type_iterate(o) {
3100
game.info.min_city_center_output[o]
3101
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3102
RS_DEFAULT_CITY_CENTER_OUTPUT,
3103
RS_MIN_CITY_CENTER_OUTPUT,
3104
RS_MAX_CITY_CENTER_OUTPUT,
3105
"civstyle.min_city_center_%s",
3106
get_output_identifier(o));
3107
} output_type_iterate_end;
3109
sval = secfile_lookup_str(&file, "civstyle.nuke_contamination" );
3110
if (mystrcasecmp(sval, "Pollution") == 0) {
3111
game.info.nuke_contamination = CONTAMINATION_POLLUTION;
3112
} else if (mystrcasecmp(sval, "Fallout") == 0) {
3113
game.info.nuke_contamination = CONTAMINATION_FALLOUT;
3115
freelog(LOG_ERROR, "Bad value %s for nuke_contamination. Using "
3116
"\"Pollution\".", sval);
3117
game.info.nuke_contamination = CONTAMINATION_POLLUTION;
3120
/* This only takes effect if citymindist is set to 0. */
3121
game.info.min_dist_bw_cities
3122
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3123
RS_DEFAULT_CITIES_MIN_DIST,
3124
RS_MIN_CITIES_MIN_DIST,
3125
RS_MAX_CITIES_MIN_DIST,
3126
"civstyle.min_dist_bw_cities");
3127
game.info.init_vis_radius_sq
3128
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3129
RS_DEFAULT_VIS_RADIUS_SQ,
3130
RS_MIN_VIS_RADIUS_SQ,
3131
RS_MAX_VIS_RADIUS_SQ,
3132
"civstyle.init_vis_radius_sq");
3134
game.info.gold_upkeep_style
3135
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3136
RS_DEFAULT_GOLD_UPKEEP_STYLE,
3137
RS_MIN_GOLD_UPKEEP_STYLE,
3138
RS_MAX_GOLD_UPKEEP_STYLE,
3139
"civstyle.gold_upkeep_style");
3141
/* TODO: move to new section research */
3142
game.info.tech_cost_style
3143
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3144
RS_DEFAULT_TECH_COST_STYLE,
3145
RS_MIN_TECH_COST_STYLE,
3146
RS_MAX_TECH_COST_STYLE,
3147
"civstyle.tech_cost_style");
3148
/* TODO: move to new section research */
3149
game.info.tech_leakage
3150
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3151
RS_DEFAULT_TECH_LEAKAGE,
3152
RS_MIN_TECH_LEAKAGE,
3153
RS_MAX_TECH_LEAKAGE,
3154
"civstyle.tech_leakage");
2697
3155
if (game.info.tech_cost_style == 0 && game.info.tech_leakage != 0) {
2698
3156
freelog(LOG_ERROR,
2699
"Only tech_leakage 0 supported with tech_cost_style 0.");
3157
"Only tech_leakage 0 supported with tech_cost_style 0.");
2700
3158
freelog(LOG_ERROR, "Switching to tech_leakage 0.");
2701
3159
game.info.tech_leakage = 0;
2704
/* City incite cost */
2705
game.info.base_incite_cost =
2706
secfile_lookup_int_default(&file, 1000, "incite_cost.base_incite_cost");
2707
game.info.incite_improvement_factor =
2708
secfile_lookup_int_default(&file, 1, "incite_cost.improvement_factor");
2709
game.info.incite_unit_factor =
2710
secfile_lookup_int_default(&file, 1, "incite_cost.unit_factor");
2711
game.info.incite_total_factor =
2712
secfile_lookup_int_default(&file, 100, "incite_cost.total_factor");
2714
/* Slow invasions */
2715
game.info.slow_invasions =
2716
secfile_lookup_bool_default(&file, GAME_DEFAULT_SLOW_INVASIONS,
2717
"global_unit_options.slow_invasions");
2719
/* Load global initial items. */
2720
lookup_tech_list(&file, "options", "global_init_techs",
2721
game.rgame.global_init_techs, filename);
2722
lookup_building_list(&file, "options", "global_init_buildings",
2723
game.rgame.global_init_buildings, filename);
2725
/* Enable/Disable killstack */
2726
game.info.killstack = secfile_lookup_bool(&file, "combat_rules.killstack");
3162
/* section: illness */
3163
game.info.illness_on
3164
= secfile_lookup_bool_default(&file, RS_DEFAULT_ILLNESS_ON,
3165
"illness.illness_on");
3166
game.info.illness_base_factor
3167
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3168
RS_DEFAULT_ILLNESS_BASE_FACTOR,
3169
RS_MIN_ILLNESS_BASE_FACTOR,
3170
RS_MAX_ILLNESS_BASE_FACTOR,
3171
"illness.illness_base_factor");
3172
game.info.illness_min_size
3173
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3174
RS_DEFAULT_ILLNESS_MIN_SIZE,
3175
RS_MIN_ILLNESS_MIN_SIZE,
3176
RS_MAX_ILLNESS_MIN_SIZE,
3177
"illness.illness_min_size");
3178
game.info.illness_trade_infection
3179
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3180
RS_DEFAULT_ILLNESS_TRADE_INFECTION_PCT,
3181
RS_MIN_ILLNESS_TRADE_INFECTION_PCT,
3182
RS_MAX_ILLNESS_TRADE_INFECTION_PCT,
3183
"illness.illness_trade_infection");
3184
game.info.illness_pollution_factor
3185
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3186
RS_DEFAULT_ILLNESS_POLLUTION_PCT,
3187
RS_MIN_ILLNESS_POLLUTION_PCT,
3188
RS_MAX_ILLNESS_POLLUTION_PCT,
3189
"illness.illness_pollution_factor");
3191
/* section: incite_cost */
3192
game.info.base_incite_cost
3193
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3194
RS_DEFAULT_INCITE_BASE_COST,
3195
RS_MIN_INCITE_BASE_COST,
3196
RS_MAX_INCITE_BASE_COST,
3197
"incite_cost.base_incite_cost");
3198
game.info.incite_improvement_factor
3199
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3200
RS_DEFAULT_INCITE_IMPROVEMENT_FCT,
3201
RS_MIN_INCITE_IMPROVEMENT_FCT,
3202
RS_MAX_INCITE_IMPROVEMENT_FCT,
3203
"incite_cost.improvement_factor");
3204
game.info.incite_unit_factor
3205
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3206
RS_DEFAULT_INCITE_UNIT_FCT,
3207
RS_MIN_INCITE_UNIT_FCT,
3208
RS_MAX_INCITE_UNIT_FCT,
3209
"incite_cost.unit_factor");
3210
game.info.incite_total_factor
3211
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3212
RS_DEFAULT_INCITE_TOTAL_FCT,
3213
RS_MIN_INCITE_TOTAL_FCT,
3214
RS_MAX_INCITE_TOTAL_FCT,
3215
"incite_cost.total_factor");
3217
/* section: global_unit_options */
3218
game.info.slow_invasions
3219
= secfile_lookup_bool_default(&file, RS_DEFAULT_SLOW_INVASIONS,
3220
"global_unit_options.slow_invasions");
3222
/* section: combat_rules */
3224
= secfile_lookup_bool_default(&file, RS_DEFAULT_KILLSTACK,
3225
"combat_rules.killstack");
3226
game.info.tired_attack
3227
= secfile_lookup_bool_default(&file, RS_DEFAULT_TIRED_ATTACK,
3228
"combat_rules.tired_attack");
3230
/* section: borders */
3231
game.info.border_city_radius_sq
3232
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3233
RS_DEFAULT_BORDER_RADIUS_SQ_CITY,
3234
RS_MIN_BORDER_RADIUS_SQ_CITY,
3235
RS_MAX_BORDER_RADIUS_SQ_CITY,
3236
"borders.radius_sq_city");
3237
game.info.border_size_effect
3238
= secfile_lookup_int_default_min_max(ruleset_error, &file,
3239
RS_DEFAULT_BORDER_SIZE_EFFECT,
3240
RS_MIN_BORDER_SIZE_EFFECT,
3241
RS_MAX_BORDER_SIZE_EFFECT,
3242
"borders.size_effect");
3244
/* section: calendar */
3245
game.info.calendar_skip_0
3246
= secfile_lookup_bool_default(&file, RS_DEFAULT_CALENDAR_SKIP_0,
3247
"calendar.skip_year_0");
3248
game.info.start_year
3249
= secfile_lookup_int_default(&file, GAME_START_YEAR,
3250
"calendar.start_year");
3251
sz_strlcpy(game.info.positive_year_label,
3252
_(secfile_lookup_str_default(&file,
3253
RS_DEFAULT_POS_YEAR_LABEL,
3254
"calendar.positive_label")));
3255
sz_strlcpy(game.info.negative_year_label,
3256
_(secfile_lookup_str_default(&file,
3257
RS_DEFAULT_NEG_YEAR_LABEL,
3258
"calendar.negative_label")));
3260
/* section: teams */
2728
3261
svec = secfile_lookup_str_vec(&file, &game.info.num_teams, "teams.names");
2729
3262
game.info.num_teams = MIN(MAX_NUM_TEAMS, game.info.num_teams);
2730
3263
if (game.info.num_teams <= 0) {
2731
freelog(LOG_FATAL, "Missing team names in game.ruleset.");
3264
ruleset_error(LOG_FATAL, "Missing team names in game.ruleset.");
2734
3266
for (i = 0; i < game.info.num_teams; i++) {
2735
3267
sz_strlcpy(game.info.team_names_orig[i], svec[i]);