~ubuntu-branches/debian/sid/freeciv/sid

« back to all changes in this revision

Viewing changes to server/ruleset.c

  • Committer: Package Import Robot
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2011-08-28 22:40:00 UTC
  • mfrom: (1.2.19 upstream)
  • Revision ID: package-import@ubuntu.com-20110828224000-j2r1erewlem25dox
Tags: 2.3.0-1
[ Karl Goetz ]
* New upstream version.
* Fix themes_sdl_use_system_fonts.diff to apply cleanly on 2.3.0
* Massage work_around_unity_induced_breakage.diff to get it
  applying to the new codebase (The patch assumes commits made
  after 2.3.0 was tagged upstream).

[ Clint Adams ]
* Fudge build system to think there is no libtool mismatch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
#include <config.h>
16
16
#endif
17
17
 
18
 
#include <assert.h>
19
18
#include <stdarg.h>
20
19
#include <stdio.h>
21
20
#include <stdlib.h>
22
21
#include <string.h>
23
22
 
24
23
/* utility */
 
24
#include "bitvector.h"
25
25
#include "fcintl.h"
26
26
#include "log.h"
27
27
#include "mem.h"
28
28
#include "registry.h"
29
29
#include "shared.h"
 
30
#include "string_vector.h"
30
31
#include "support.h"
31
32
 
32
33
/* common */
38
39
#include "government.h"
39
40
#include "map.h"
40
41
#include "movement.h"
 
42
#include "name_translation.h"
41
43
#include "nation.h"
42
44
#include "packets.h"
43
45
#include "requirements.h"
45
47
#include "tech.h"
46
48
#include "unit.h"
47
49
 
 
50
/* ai */
 
51
#include "aiunit.h"     /* update_simple_ai_types */
 
52
 
48
53
/* server */
49
54
#include "citytools.h"
50
55
#include "plrhand.h"
51
56
#include "script.h"
52
 
 
53
 
#include "aiunit.h"             /* update_simple_ai_types */
 
57
#include "settings.h"
 
58
#include "srv_main.h"
54
59
 
55
60
#include "ruleset.h"
56
 
#include "srv_main.h"
 
61
 
 
62
 
 
63
/* Basic format for the ruleset files for Freeciv versions 2.3.x. */
 
64
#define RULESET_CAPABILITIES "+Freeciv-2.3-ruleset"
57
65
 
58
66
/* RULESET_SUFFIX already used, no leading dot here */
59
67
#define RULES_SUFFIX "ruleset"
69
77
#define RESOURCE_SECTION_PREFIX "resource_"
70
78
#define BASE_SECTION_PREFIX "base_"
71
79
#define SPECIALIST_SECTION_PREFIX "specialist_"
72
 
#define TERRAIN_CAPABILITY "+1.9+2007.Oct.26"
73
80
#define TERRAIN_SECTION_PREFIX "terrain_"
74
81
#define UNIT_CLASS_SECTION_PREFIX "unitclass_"
75
82
#define UNIT_SECTION_PREFIX "unit_"
76
83
 
 
84
#define check_name(name) (check_strlen(name, MAX_LEN_NAME, NULL))
 
85
 
 
86
/* avoid re-reading files */
77
87
static const char name_too_long[] = "Name \"%s\" too long; truncating.";
78
 
#define check_name(name) (check_strlen(name, MAX_LEN_NAME, name_too_long))
79
 
#define name_strlcpy(dst, src) \
80
 
        ((void) sz_loud_strlcpy(dst, src, name_too_long))
81
 
 
82
 
/* avoid re-reading files */
83
88
#define MAX_SECTION_LABEL 64
84
89
#define section_strlcpy(dst, src) \
85
90
        (void) loud_strlcpy(dst, src, MAX_SECTION_LABEL, name_too_long)
87
92
static char *terrain_sections = NULL;
88
93
static char *base_sections = NULL;
89
94
 
90
 
 
91
 
static void openload_ruleset_file(struct section_file *file,
92
 
                                  const char *whichset);
93
 
static char *check_ruleset_capabilities(struct section_file *file,
94
 
                                        const char *us_capstr,
95
 
                                        const char *filename);
 
95
static struct section_file *openload_ruleset_file(const char *whichset);
 
96
static const char *check_ruleset_capabilities(struct section_file *file,
 
97
                                              const char *us_capstr,
 
98
                                              const char *filename);
96
99
 
97
100
static void load_tech_names(struct section_file *file);
98
101
static void load_unit_names(struct section_file *file);
101
104
static void load_terrain_names(struct section_file *file);
102
105
static void load_citystyle_names(struct section_file *file);
103
106
static void load_nation_names(struct section_file *file);
104
 
static struct nation_city* load_city_name_list(struct section_file *file,
105
 
                                             const char *secfile_str1,
106
 
                                             const char *secfile_str2);
 
107
static void load_city_name_list(struct section_file *file,
 
108
                                struct nation_type *pnation,
 
109
                                const char *secfile_str1,
 
110
                                const char *secfile_str2);
107
111
 
108
112
static void load_ruleset_techs(struct section_file *file);
109
113
static void load_ruleset_units(struct section_file *file);
125
129
static void send_ruleset_governments(struct conn_list *dest);
126
130
static void send_ruleset_cities(struct conn_list *dest);
127
131
static void send_ruleset_game(struct conn_list *dest);
 
132
static void send_ruleset_team_names(struct conn_list *dest);
128
133
 
129
134
static bool nation_has_initial_tech(struct nation_type *pnation,
130
135
                                    struct advance *tech);
131
136
static bool sanity_check_ruleset_data(void);
132
 
static void ruleset_error(int loglevel, const char *format, ...)
133
 
                          fc__attribute((__format__ (__printf__, 2, 3)));
 
137
static void ruleset_error_real(const char *file, const char *function,
 
138
                               int line, enum log_level level,
 
139
                               const char *format, ...)
 
140
                               fc__attribute((__format__ (__printf__, 5, 6)));
 
141
#define ruleset_error(level, format, ...)                                   \
 
142
  if (log_do_output_for_level(level)) {                                     \
 
143
    ruleset_error_real(__FILE__, __FUNCTION__, __LINE__,                    \
 
144
                       level, format, ## __VA_ARGS__);                      \
 
145
  }
134
146
 
135
147
/**************************************************************************
136
148
  Notifications about ruleset errors to clients. Especially important in
137
149
  case of internal server crashing.
138
150
**************************************************************************/
139
 
static void ruleset_error(int loglevel, const char *format, ...)
 
151
static void ruleset_error_real(const char *file, const char *function,
 
152
                               int line, enum log_level level,
 
153
                               const char *format, ...)
140
154
{
141
155
  va_list args;
142
156
 
143
157
  va_start(args, format);
144
 
 
145
 
  vreal_freelog(loglevel, format, args);
146
 
 
 
158
  vdo_log(file, function, line, FALSE, level, format, args);
147
159
  va_end(args);
148
160
 
149
 
  if (LOG_FATAL >= loglevel) {
 
161
  if (LOG_FATAL >= level) {
150
162
    exit(EXIT_FAILURE);
151
163
  }
152
164
}
155
167
  datafilename() wrapper: tries to match in two ways.
156
168
  Returns NULL on failure, the (statically allocated) filename on success.
157
169
**************************************************************************/
158
 
static char *valid_ruleset_filename(const char *subdir,
159
 
                                    const char *name, const char *extension)
 
170
static const char *valid_ruleset_filename(const char *subdir,
 
171
                                          const char *name,
 
172
                                          const char *extension)
160
173
{
161
 
  char filename[512], *dfilename;
162
 
 
163
 
  assert(subdir && name && extension);
164
 
 
165
 
  my_snprintf(filename, sizeof(filename), "%s/%s.%s", subdir, name, extension);
166
 
  freelog(LOG_VERBOSE, "Trying \"%s\".",
167
 
                       filename);
168
 
  dfilename = datafilename(filename);
169
 
  if (dfilename) {
170
 
    return dfilename;
171
 
  }
172
 
 
173
 
  my_snprintf(filename, sizeof(filename), "default/%s.%s", name, extension);
174
 
  freelog(LOG_VERBOSE, "Trying \"%s\": default ruleset directory.",
175
 
                       filename);
176
 
  dfilename = datafilename(filename);
177
 
  if (dfilename) {
178
 
    return dfilename;
179
 
  }
180
 
 
181
 
  my_snprintf(filename, sizeof(filename), "%s_%s.%s", subdir, name, extension);
182
 
  freelog(LOG_VERBOSE, "Trying \"%s\": alternative ruleset filename syntax.",
183
 
                       filename);
184
 
  dfilename = datafilename(filename);
 
174
  char filename[512];
 
175
  const char *dfilename;
 
176
 
 
177
  fc_assert_ret_val(subdir && name && extension, NULL);
 
178
 
 
179
  fc_snprintf(filename, sizeof(filename), "%s/%s.%s",
 
180
              subdir, name, extension);
 
181
  log_verbose("Trying \"%s\".", filename);
 
182
  dfilename = fileinfoname(get_data_dirs(), filename);
 
183
  if (dfilename) {
 
184
    return dfilename;
 
185
  }
 
186
 
 
187
  fc_snprintf(filename, sizeof(filename), "default/%s.%s", name, extension);
 
188
  log_verbose("Trying \"%s\": default ruleset directory.", filename);
 
189
  dfilename = fileinfoname(get_data_dirs(), filename);
 
190
  if (dfilename) {
 
191
    return dfilename;
 
192
  }
 
193
 
 
194
  fc_snprintf(filename, sizeof(filename), "%s_%s.%s",
 
195
              subdir, name, extension);
 
196
  log_verbose("Trying \"%s\": alternative ruleset filename syntax.",
 
197
              filename);
 
198
  dfilename = fileinfoname(get_data_dirs(), filename);
185
199
  if (dfilename) {
186
200
    return dfilename;
187
201
  } else {
198
212
  Do initial section_file_load on a ruleset file.
199
213
  "whichset" = "techs", "units", "buildings", "terrain", ...
200
214
**************************************************************************/
201
 
static void openload_ruleset_file(struct section_file *file,
202
 
                                  const char *whichset)
 
215
static struct section_file *openload_ruleset_file(const char *whichset)
203
216
{
204
217
  char sfilename[512];
205
 
  char *dfilename = valid_ruleset_filename(game.server.rulesetdir,
206
 
                                           whichset, RULES_SUFFIX);
 
218
  const char *dfilename = valid_ruleset_filename(game.server.rulesetdir,
 
219
                                                 whichset, RULES_SUFFIX);
 
220
  struct section_file *secfile;
207
221
 
208
222
  /* Need to save a copy of the filename for following message, since
209
223
     section_file_load() may call datafilename() for includes. */
210
224
 
211
225
  sz_strlcpy(sfilename, dfilename);
212
226
 
213
 
  if (!section_file_load_nodup(file, sfilename)) {
214
 
    ruleset_error(LOG_FATAL, "\"%s\": could not load ruleset.",
215
 
                  sfilename);
 
227
  if (!(secfile = secfile_load(sfilename, FALSE))) {
 
228
    ruleset_error(LOG_FATAL, "Could not load ruleset '%s':\n%s",
 
229
                  sfilename, secfile_error());
216
230
  }
 
231
  return secfile;
217
232
}
218
233
 
219
234
/**************************************************************************
221
236
**************************************************************************/
222
237
static void openload_script_file(const char *whichset)
223
238
{
224
 
  char *dfilename = valid_ruleset_filename(game.server.rulesetdir,
225
 
                                           whichset, SCRIPT_SUFFIX);
 
239
  const char *dfilename = valid_ruleset_filename(game.server.rulesetdir,
 
240
                                                 whichset, SCRIPT_SUFFIX);
226
241
 
227
242
  if (!script_do_file(dfilename)) {
228
243
    ruleset_error(LOG_FATAL, "\"%s\": could not load ruleset script.",
235
250
  This gets and returns that string, and checks that the required
236
251
  capabilities specified are satisified.
237
252
**************************************************************************/
238
 
static char *check_ruleset_capabilities(struct section_file *file,
239
 
                                        const char *us_capstr, const char *filename)
 
253
static const char *check_ruleset_capabilities(struct section_file *file,
 
254
                                              const char *us_capstr,
 
255
                                              const char *filename)
240
256
{
241
 
  char *datafile_options;
242
 
  
243
 
  datafile_options = secfile_lookup_str(file, "datafile.options");
 
257
  const char *datafile_options;
 
258
 
 
259
  if (!(datafile_options = secfile_lookup_str(file, "datafile.options"))) {
 
260
    log_fatal("\"%s\": ruleset capability problem:", filename);
 
261
    ruleset_error(LOG_FATAL, "%s", secfile_error());
 
262
  }
244
263
  if (!has_capabilities(us_capstr, datafile_options)) {
245
 
    freelog(LOG_FATAL, "\"%s\": ruleset datafile appears incompatible:",
246
 
                        filename);
247
 
    freelog(LOG_FATAL, "  datafile options: %s", datafile_options);
248
 
    freelog(LOG_FATAL, "  supported options: %s", us_capstr);
 
264
    log_fatal("\"%s\": ruleset datafile appears incompatible:", filename);
 
265
    log_fatal("  datafile options: %s", datafile_options);
 
266
    log_fatal("  supported options: %s", us_capstr);
249
267
    ruleset_error(LOG_FATAL, "Capability problem");
250
268
  }
251
269
  if (!has_capabilities(datafile_options, us_capstr)) {
252
 
    freelog(LOG_FATAL, "\"%s\": ruleset datafile claims required option(s)"
253
 
                         " that we don't support:", filename);
254
 
    freelog(LOG_FATAL, "  datafile options: %s", datafile_options);
255
 
    freelog(LOG_FATAL, "  supported options: %s", us_capstr);
 
270
    log_fatal("\"%s\": ruleset datafile claims required option(s)"
 
271
              " that we don't support:", filename);
 
272
    log_fatal("  datafile options: %s", datafile_options);
 
273
    log_fatal("  supported options: %s", us_capstr);
256
274
    ruleset_error(LOG_FATAL, "Capability problem");
257
275
  }
258
276
  return datafile_options;
267
285
                                                  const char *sub,
268
286
                                                  const char *rfor)
269
287
{
270
 
  char *type, *name;
 
288
  const char *type, *name;
271
289
  int j;
272
290
  const char *filename;
273
291
  static struct requirement_vector list;
274
292
 
275
 
  filename = secfile_filename(file);
 
293
  filename = secfile_name(file);
276
294
 
277
295
  requirement_vector_reserve(&list, 0);
278
296
 
279
 
  for (j = 0;
280
 
      (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
281
 
                                         sec, sub, j));
282
 
      j++) {
283
 
    char *range;
 
297
  for (j = 0; (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
 
298
                                                 sec, sub, j)); j++) {
 
299
    char buf[MAX_LEN_NAME];
 
300
    const char *range;
284
301
    bool survives, negated;
 
302
    struct entry *pentry;
285
303
    struct requirement req;
286
304
 
287
 
    name = secfile_lookup_str(file, "%s.%s%d.name", sec, sub, j);
288
 
    range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j);
 
305
    if (!(pentry = secfile_entry_lookup(file, "%s.%s%d.name",
 
306
                                        sec, sub, j))) {
 
307
      log_error("%s", secfile_error());
 
308
      continue;
 
309
    }
 
310
    name = NULL;
 
311
    switch (entry_type(pentry)) {
 
312
    case ENTRY_BOOL:
 
313
      {
 
314
        bool val;
 
315
 
 
316
        if (entry_bool_get(pentry, &val)) {
 
317
          fc_snprintf(buf, sizeof(buf), "%d", val);
 
318
          name = buf;
 
319
        }
 
320
      }
 
321
      break;
 
322
    case ENTRY_INT:
 
323
      {
 
324
        int val;
 
325
 
 
326
        if (entry_int_get(pentry, &val)) {
 
327
          fc_snprintf(buf, sizeof(buf), "%d", val);
 
328
          name = buf;
 
329
        }
 
330
      }
 
331
      break;
 
332
    case ENTRY_STR:
 
333
      (void) entry_str_get(pentry, &name);
 
334
      break;
 
335
    }
 
336
    if (NULL == name) {
 
337
      log_error("\"%s\": error in handling requirement name for '%s.%s%d'.",
 
338
                filename, sec, sub, j);
 
339
      continue;
 
340
    }
 
341
 
 
342
    if (!(range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j))) {
 
343
      log_error("%s", secfile_error());
 
344
      continue;
 
345
    }
289
346
 
290
347
    survives = secfile_lookup_bool_default(file, FALSE,
291
348
        "%s.%s%d.survives", sec, sub, j);
293
350
        "%s.%s%d.negated", sec, sub, j);
294
351
 
295
352
    req = req_from_str(type, range, survives, negated, name);
296
 
    if (VUT_LAST == req.source.kind) {
 
353
    if (req.source.kind == universals_n_invalid()) {
297
354
      /* Error.  Log it, clear the req and continue. */
298
 
      freelog(LOG_ERROR,
299
 
          "\"%s\" [%s] has unknown req: \"%s\" \"%s\".",
300
 
          filename, sec, type, name);
 
355
      log_error("\"%s\" [%s] has unknown req: \"%s\" \"%s\".",
 
356
                filename, sec, type, name);
301
357
      req.source.kind = VUT_NONE;
302
358
    }
303
359
 
304
 
    requirement_vector_append(&list, &req);
 
360
    requirement_vector_append(&list, req);
305
361
  }
306
362
 
307
363
  if (j > MAX_NUM_REQS) {
325
381
                                   int loglevel, const char *filename,
326
382
                                   const char *description)
327
383
{
328
 
  char *sval;
 
384
  const char *sval;
329
385
  struct advance *padvance;
330
386
  
331
387
  sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
332
388
  if (!sval || (LOG_FATAL < loglevel && strcmp(sval, "Never") == 0)) {
333
389
    padvance = A_NEVER;
334
390
  } else {
335
 
    padvance = find_advance_by_rule_name(sval);
 
391
    padvance = advance_by_rule_name(sval);
336
392
 
337
393
    if (A_NEVER == padvance) {
338
394
      ruleset_error(loglevel,
357
413
                                         int loglevel, const char *filename,
358
414
                                         const char *description)
359
415
{
360
 
  char *sval;
 
416
  const char *sval;
361
417
  struct impr_type *pimprove;
362
418
  
363
419
  sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
364
420
  if (!sval || (LOG_FATAL < loglevel && strcmp(sval, "None") == 0)) {
365
421
    pimprove = B_NEVER;
366
422
  } else {
367
 
    pimprove = find_improvement_by_rule_name(sval);
 
423
    pimprove = improvement_by_rule_name(sval);
368
424
 
369
425
    if (B_NEVER == pimprove) {
370
426
      ruleset_error(loglevel,
385
441
 we report it as an error, otherwise we just punt.
386
442
**************************************************************************/
387
443
static void lookup_unit_list(struct section_file *file, const char *prefix,
388
 
                             const char *entry, int loglevel,
389
 
                             struct unit_type **output, 
 
444
                             const char *entry, int loglevel,
 
445
                             struct unit_type **output, 
390
446
                             const char *filename)
391
447
{
392
 
  char **slist;
393
 
  int i, nval;
 
448
  const char **slist;
 
449
  size_t nval;
 
450
  int i;
394
451
 
395
452
  /* pre-fill with NULL: */
396
453
  for(i = 0; i < MAX_NUM_UNIT_LIST; i++) {
407
464
  if (nval > MAX_NUM_UNIT_LIST) {
408
465
    ruleset_error(LOG_FATAL,
409
466
                  "\"%s\": string vector %s.%s too long (%d, max %d)",
410
 
                  filename, prefix, entry, nval, MAX_NUM_UNIT_LIST);
 
467
                  filename, prefix, entry, (int) nval, MAX_NUM_UNIT_LIST);
411
468
  }
412
469
  if (nval == 1 && strcmp(slist[0], "") == 0) {
413
470
    free(slist);
414
471
    return;
415
472
  }
416
473
  for (i = 0; i < nval; i++) {
417
 
    char *sval = slist[i];
418
 
    struct unit_type *punittype = find_unit_type_by_rule_name(sval);
 
474
    const char *sval = slist[i];
 
475
    struct unit_type *punittype = unit_type_by_rule_name(sval);
419
476
 
420
477
    if (!punittype) {
421
478
      ruleset_error(LOG_FATAL,
423
480
                    filename, prefix, entry, i, sval);
424
481
    }
425
482
    output[i] = punittype;
426
 
    freelog(LOG_DEBUG, "\"%s\" %s.%s (%d): %s (%d)",
427
 
            filename, prefix, entry, i, sval,
428
 
            utype_number(punittype));
 
483
    log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
 
484
              utype_number(punittype));
429
485
  }
430
486
  free(slist);
431
487
  return;
440
496
 meaning empty list.
441
497
**************************************************************************/
442
498
static void lookup_tech_list(struct section_file *file, const char *prefix,
443
 
                             const char *entry, int *output, const char *filename)
 
499
                             const char *entry, int *output,
 
500
                             const char *filename)
444
501
{
445
 
  char **slist;
446
 
  int i, nval;
 
502
  const char **slist;
 
503
  size_t nval;
 
504
  int i;
447
505
 
448
506
  /* pre-fill with A_LAST: */
449
507
  for(i=0; i<MAX_NUM_TECH_LIST; i++) {
457
515
  if (nval>MAX_NUM_TECH_LIST) {
458
516
    ruleset_error(LOG_FATAL,
459
517
                  "\"%s\": string vector %s.%s too long (%d, max %d)",
460
 
                  filename, prefix, entry, nval, MAX_NUM_TECH_LIST);
 
518
                  filename, prefix, entry, (int) nval, MAX_NUM_TECH_LIST);
461
519
  }
462
520
  if (nval==1 && strcmp(slist[0], "")==0) {
463
521
    free(slist);
464
522
    return;
465
523
  }
466
524
  for (i=0; i<nval; i++) {
467
 
    char *sval = slist[i];
468
 
    struct advance *padvance = find_advance_by_rule_name(sval);
 
525
    const char *sval = slist[i];
 
526
    struct advance *padvance = advance_by_rule_name(sval);
469
527
 
470
528
    if (NULL == padvance) {
471
529
      ruleset_error(LOG_FATAL,
477
535
                    filename, prefix, entry, i, sval);
478
536
    }
479
537
    output[i] = advance_number(padvance);
480
 
    freelog(LOG_DEBUG, "\"%s\" %s.%s (%d): %s (%d)",
481
 
            filename, prefix, entry, i, sval,
482
 
            advance_number(padvance));
 
538
    log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
 
539
              advance_number(padvance));
483
540
  }
484
541
  free(slist);
485
542
  return;
493
550
  improvement_exist()?] There should be at least one value, but it may be
494
551
  "", meaning an empty list.
495
552
**************************************************************************/
496
 
static void lookup_building_list(struct section_file *file, const char *prefix,
497
 
                                 const char *entry, int *output,
498
 
                                 const char *filename)
 
553
static void lookup_building_list(struct section_file *file,
 
554
                                 const char *prefix, const char *entry,
 
555
                                 int *output, const char *filename)
499
556
{
500
 
  char **slist;
501
 
  int i, nval;
 
557
  const char **slist;
 
558
  size_t nval;
 
559
  int i;
502
560
 
503
561
  /* pre-fill with B_LAST: */
504
562
  for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
512
570
  if (nval > MAX_NUM_BUILDING_LIST) {
513
571
    ruleset_error(LOG_FATAL,
514
572
                  "\"%s\": string vector %s.%s too long (%d, max %d)",
515
 
                  filename, prefix, entry, nval, MAX_NUM_BUILDING_LIST);
 
573
                  filename, prefix, entry, (int) nval, MAX_NUM_BUILDING_LIST);
516
574
  }
517
575
  if (nval == 1 && strcmp(slist[0], "") == 0) {
518
576
    free(slist);
519
577
    return;
520
578
  }
521
579
  for (i = 0; i < nval; i++) {
522
 
    char *sval = slist[i];
523
 
    struct impr_type *pimprove = find_improvement_by_rule_name(sval);
 
580
    const char *sval = slist[i];
 
581
    struct impr_type *pimprove = improvement_by_rule_name(sval);
524
582
 
525
583
    if (NULL == pimprove) {
526
584
      ruleset_error(LOG_FATAL,
528
586
                    filename, prefix, entry, i, sval);
529
587
    }
530
588
    output[i] = improvement_number(pimprove);
531
 
    freelog(LOG_DEBUG, "%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
 
589
    log_debug("%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
532
590
  }
533
591
  free(slist);
534
592
}
547
605
                                          const char *filename,
548
606
                                          const char *description)
549
607
{
550
 
  char *sval;
 
608
  const char *sval;
551
609
  struct unit_type *punittype;
552
610
  
553
611
  if (LOG_FATAL >= loglevel) {
559
617
  if (strcmp(sval, "None")==0) {
560
618
    punittype = NULL;
561
619
  } else {
562
 
    punittype = find_unit_type_by_rule_name(sval);
 
620
    punittype = unit_type_by_rule_name(sval);
563
621
    if (!punittype) {
564
622
      ruleset_error(loglevel,
565
623
                    "\"%s\" %s %s: couldn't match \"%s\".",
580
638
                                            const char *entry,
581
639
                                            const char *filename)
582
640
{
583
 
  char *sval;
 
641
  const char *sval;
584
642
  struct government *gov;
585
643
  
586
644
  sval = secfile_lookup_str(file, "%s", entry);
587
 
  gov = find_government_by_rule_name(sval);
 
645
  gov = government_by_rule_name(sval);
588
646
  if (!gov) {
589
647
    ruleset_error(LOG_FATAL,
590
648
                  "\"%s\" %s: couldn't match \"%s\".",
601
659
                                            const char *entry,
602
660
                                            const char *filename)
603
661
{
604
 
  char *sval;
 
662
  const char *sval;
605
663
  enum unit_move_type mt;
606
664
  
607
665
  sval = secfile_lookup_str(file, "%s", entry);
614
672
  return mt;
615
673
}
616
674
 
617
 
/**************************************************************************
 
675
/****************************************************************************
618
676
  Lookup optional string, returning allocated memory or NULL.
619
 
**************************************************************************/
 
677
****************************************************************************/
620
678
static char *lookup_string(struct section_file *file, const char *prefix,
621
 
                           const char *suffix)
 
679
                           const char *suffix)
622
680
{
623
 
  char *sval;
624
 
  
625
 
  sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, suffix);
626
 
  if (sval) {
627
 
    sval = skip_leading_spaces(sval);
628
 
    if (strlen(sval) > 0) {
629
 
      return mystrdup(sval);
 
681
  const char *sval = secfile_lookup_str(file, "%s.%s", prefix, suffix);
 
682
 
 
683
  if (NULL != sval) {
 
684
    char copy[strlen(sval) + 1];
 
685
 
 
686
    strcpy(copy, sval);
 
687
    remove_leading_trailing_spaces(copy);
 
688
    if (strlen(copy) > 0) {
 
689
      return fc_strdup(copy);
630
690
    }
631
691
  }
632
692
  return NULL;
633
693
}
634
694
 
635
 
/**************************************************************************
636
 
  Lookup optional helptext, returning allocated memory or NULL.
637
 
**************************************************************************/
638
 
static char *lookup_helptext(struct section_file *file, const char *prefix)
 
695
/****************************************************************************
 
696
  Lookup optional string vector, returning allocated memory or NULL.
 
697
****************************************************************************/
 
698
static struct strvec *lookup_strvec(struct section_file *file,
 
699
                                    const char *prefix, const char *suffix)
639
700
{
640
 
  return lookup_string(file, prefix, "helptext");
 
701
  size_t dim;
 
702
  const char **vec = secfile_lookup_str_vec(file, &dim,
 
703
                                            "%s.%s", prefix, suffix);
 
704
 
 
705
  if (NULL != vec) {
 
706
    struct strvec *dest = strvec_new();
 
707
 
 
708
    strvec_store(dest, vec, dim);
 
709
    free(vec);
 
710
    return dest;
 
711
  }
 
712
  return NULL;
641
713
}
642
714
 
643
715
/**************************************************************************
650
722
  resource_type_iterate(presource) {
651
723
    const int i = resource_index(presource);
652
724
    const char *isection = &resource_sections[i * MAX_SECTION_LABEL];
653
 
    if (0 == mystrcasecmp(isection, name)) {
 
725
    if (0 == fc_strcasecmp(isection, name)) {
654
726
      return presource;
655
727
    }
656
728
  } resource_type_iterate_end;
672
744
{
673
745
  const int j = terrain_index(pthis);
674
746
  const char *jsection = &terrain_sections[j * MAX_SECTION_LABEL];
675
 
  char *name = secfile_lookup_str(file, "%s.%s", jsection, item);
 
747
  const char *name = secfile_lookup_str(file, "%s.%s", jsection, item);
676
748
 
677
749
  if (NULL == name
678
750
      || *name == '\0'
687
759
  terrain_type_iterate(pterrain) {
688
760
    const int i = terrain_index(pterrain);
689
761
    const char *isection = &terrain_sections[i * MAX_SECTION_LABEL];
690
 
    if (0 == mystrcasecmp(isection, name)) {
 
762
    if (0 == fc_strcasecmp(isection, name)) {
691
763
      return pterrain;
692
764
    }
693
765
  } terrain_type_iterate_end;
694
766
 
695
 
  ruleset_error(LOG_ERROR,
696
 
                "\"%s\" [%s] has unknown \"%s\".",
697
 
                secfile_filename(file),
698
 
                jsection,
699
 
                name);
 
767
  ruleset_error(LOG_ERROR, "\"%s\" [%s] has unknown \"%s\".",
 
768
                secfile_name(file), jsection, name);
700
769
  return T_NONE;
701
770
}
702
771
 
703
772
/**************************************************************************
 
773
  Load "name" and (optionally) "rule_name" into a struct name_translation.
 
774
**************************************************************************/
 
775
static void ruleset_load_names(struct name_translation *pname,
 
776
                               struct section_file *file,
 
777
                               const char *sec_name)
 
778
{
 
779
  const char *name = secfile_lookup_str(file, "%s.name", sec_name);
 
780
  const char *rule_name = secfile_lookup_str(file, "%s.rule_name", sec_name);
 
781
 
 
782
  if (!name) {
 
783
    ruleset_error(LOG_FATAL,
 
784
                  "\"%s\" [%s]: no \"name\" specified.",
 
785
                  secfile_name(file), sec_name);
 
786
  }
 
787
 
 
788
  names_set(pname, name, rule_name);
 
789
}
 
790
 
 
791
/**************************************************************************
704
792
  ...
705
793
**************************************************************************/
706
794
static void load_tech_names(struct section_file *file)
707
795
{
708
 
  char **sec;
709
 
  int num_techs; /* number of techs in the ruleset (means without A_NONE)*/
 
796
  struct section_list *sec;
 
797
  /* Number of techs in the ruleset (means without A_NONE). */
 
798
  int num_techs = 0;
710
799
  int i;
711
 
  const char *filename = secfile_filename(file);
 
800
  const char *filename = secfile_name(file);
712
801
 
713
 
  (void) section_file_lookup(file, "datafile.description");     /* unused */
 
802
  (void) secfile_entry_by_path(file, "datafile.description");   /* unused */
714
803
 
715
804
  /* The names: */
716
 
  sec = secfile_get_secnames_prefix(file, ADVANCE_SECTION_PREFIX, &num_techs);
717
 
  freelog(LOG_VERBOSE, "%d advances (including possibly unused)", num_techs);
718
 
  if(num_techs == 0) {
 
805
  sec = secfile_sections_by_name_prefix(file, ADVANCE_SECTION_PREFIX);
 
806
  if (NULL == sec || 0 == (num_techs = section_list_size(sec))) {
719
807
    ruleset_error(LOG_FATAL, "\"%s\": No Advances?!?", filename);
720
808
  }
 
809
  log_verbose("%d advances (including possibly unused)", num_techs);
721
810
 
722
811
  if(num_techs + A_FIRST > A_LAST_REAL) {
723
812
    ruleset_error(LOG_FATAL, "\"%s\": Too many advances (%d, max %d)",
728
817
 
729
818
  i = 0;
730
819
  advance_iterate(A_FIRST, a) {
731
 
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
732
 
    name_strlcpy(a->name.vernacular, name);
733
 
    a->name.translated = NULL;
 
820
    ruleset_load_names(&a->name, file, section_name(section_list_get(sec, i)));
734
821
    i++;
735
822
  } advance_iterate_end;
736
 
  free(sec);
 
823
  section_list_destroy(sec);
737
824
}
738
825
 
739
826
/**************************************************************************
741
828
**************************************************************************/
742
829
static void load_ruleset_techs(struct section_file *file)
743
830
{
744
 
  char **sec;
 
831
  struct section_list *sec;
745
832
  int num_techs; /* number of techs in the ruleset (means without A_NONE)*/
746
833
  int i;
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);
749
836
  
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);
752
840
 
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;
757
 
  a_none->flags = 0;
 
845
  BV_CLR_ALL(a_none->flags);
758
846
 
759
847
  i = 0;
760
848
  advance_iterate(A_FIRST, a) {
761
 
    char *sval, **slist;
762
 
    int j,ival,nval;
 
849
    const char *sec_name = section_name(section_list_get(sec, i));
 
850
    const char *sval, **slist;
 
851
    size_t nval;
 
852
    int j, ival;
763
853
 
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));
770
860
 
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\".",
774
 
              filename,
775
 
              sec[i],
776
 
              a->name.vernacular);
 
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;
778
866
    }
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.",
781
 
              filename,
782
 
              sec[i],
783
 
              a->name.vernacular);
 
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;
786
872
    }
787
873
 
788
 
    a->flags = 0;
 
874
    BV_CLR_ALL(a->flags);
789
875
 
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++) {
792
878
      sval = slist[j];
793
879
      if(strcmp(sval,"")==0) {
794
880
        continue;
795
881
      }
796
 
      ival = find_advance_flag_by_rule_name(sval);
797
 
      if (ival==TF_LAST) {
798
 
        freelog(LOG_ERROR, "\"%s\" [%s] \"%s\": bad flag name \"%s\".",
799
 
                filename,
800
 
                sec[i],
801
 
                a->name.vernacular,
802
 
                sval);
 
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);
803
886
      } else {
804
 
        a->flags |= (1<<ival);
 
887
        BV_SET(a->flags, ival);
805
888
      }
806
889
    }
807
890
    free(slist);
808
891
 
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]));
814
 
    
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));
 
897
 
 
898
    a->helptext = lookup_strvec(file, sec_name, "helptext");
 
899
    a->bonus_message = lookup_string(file, sec_name, "bonus_message");
817
900
    a->preset_cost =
818
 
        secfile_lookup_int_default(file, -1, "%s.%s", sec[i], "cost");
 
901
        secfile_lookup_int_default(file, -1, "%s.%s", sec_name, "cost");
819
902
    a->num_reqs = 0;
820
903
    
821
904
    i++;
882
965
    }
883
966
  } advance_iterate_end;
884
967
 
885
 
  free(sec);
886
 
  section_file_check_unused(file, filename);
887
 
  section_file_free(file);
 
968
  section_list_destroy(sec);
 
969
  secfile_check_unused(file);
 
970
  secfile_destroy(file);
888
971
}
889
972
 
890
973
/**************************************************************************
892
975
**************************************************************************/
893
976
static void load_unit_names(struct section_file *file)
894
977
{
895
 
  char **sec;
896
 
  int nval;
897
 
  int user_flags;
898
 
  char **flaglist;
 
978
  struct section_list *sec;
 
979
  int nval = 0;
 
980
  size_t user_flags;
 
981
  const char **flaglist;
899
982
  int i;
900
 
  const char *filename = secfile_filename(file);
 
983
  const char *filename = secfile_name(file);
901
984
 
902
 
  (void) section_file_lookup(file, "datafile.description");     /* unused */
 
985
  (void) secfile_entry_by_path(file, "datafile.description");   /* unused */
903
986
 
904
987
  /* User unit flag names */
905
 
  flaglist = secfile_lookup_str_vec(file, &user_flags,
906
 
                                    "flags.names");
 
988
  flaglist = secfile_lookup_str_vec(file, &user_flags, "flags.names");
907
989
 
908
990
  if (user_flags > MAX_NUM_USER_UNIT_FLAGS) {
909
991
    ruleset_error(LOG_FATAL, "\"%s\": Too many user unit type flags!",
921
1003
  }
922
1004
 
923
1005
  /* Unit classes */
924
 
  sec = secfile_get_secnames_prefix(file, UNIT_CLASS_SECTION_PREFIX, &nval);
925
 
  freelog(LOG_VERBOSE, "%d unit classes", nval);
926
 
  if (nval == 0) {
 
1006
  sec = secfile_sections_by_name_prefix(file, UNIT_CLASS_SECTION_PREFIX);
 
1007
  if (NULL == sec || 0 == (nval = section_list_size(sec))) {
927
1008
    ruleset_error(LOG_FATAL, "\"%s\": No unit classes?!?", filename);
928
1009
  }
 
1010
  log_verbose("%d unit classes", nval);
929
1011
  if(nval > UCL_LAST) {
930
1012
    ruleset_error(LOG_FATAL, "\"%s\": Too many unit classes (%d, max %d)",
931
1013
                  filename, nval, UCL_LAST);
935
1017
 
936
1018
  unit_class_iterate(punitclass) {
937
1019
    const int i = uclass_index(punitclass);
938
 
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
939
 
 
940
 
    name_strlcpy(punitclass->name.vernacular, name);
941
 
    punitclass->name.translated = NULL;
 
1020
    ruleset_load_names(&punitclass->name, file,
 
1021
                       section_name(section_list_get(sec, i)));
942
1022
  } unit_class_iterate_end;
943
 
  free(sec);
 
1023
  section_list_destroy(sec);
944
1024
 
945
1025
  /* The names: */
946
 
  sec = secfile_get_secnames_prefix(file, UNIT_SECTION_PREFIX, &nval);
947
 
  freelog(LOG_VERBOSE, "%d unit types (including possibly unused)", nval);
948
 
  if(nval == 0) {
 
1026
  sec = secfile_sections_by_name_prefix(file, UNIT_SECTION_PREFIX);
 
1027
  if (NULL == sec || 0 == (nval = section_list_size(sec))) {
949
1028
    ruleset_error(LOG_FATAL, "\"%s\": No unit types?!?", filename);
950
1029
  }
 
1030
  log_verbose("%d unit types (including possibly unused)", nval);
951
1031
  if(nval > U_LAST) {
952
1032
    ruleset_error(LOG_FATAL, "\"%s\": Too many unit types (%d, max %d)",
953
1033
                  filename, nval, U_LAST);
957
1037
 
958
1038
  unit_type_iterate(punittype) {
959
1039
    const int i = utype_index(punittype);
960
 
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
961
 
 
962
 
    name_strlcpy(punittype->name.vernacular, name);
963
 
    punittype->name.translated = NULL;
 
1040
    ruleset_load_names(&punittype->name, file,
 
1041
                       section_name(section_list_get(sec, i)));
964
1042
  } unit_type_iterate_end;
965
 
 
966
 
  free(sec);
 
1043
  section_list_destroy(sec);
967
1044
}
968
1045
 
969
1046
/**************************************************************************
972
1049
static void load_ruleset_units(struct section_file *file)
973
1050
{
974
1051
  struct unit_type *u;
975
 
  int i, j, ival, nval, vet_levels, vet_levels_default;
976
 
  char *sval, **slist, **sec, **csec;
977
 
  const char *filename = secfile_filename(file);
978
 
  char **vnlist, **def_vnlist;
 
1052
  int i, j, ival;
 
1053
  size_t vet_levels, vet_levels_default, nval;
 
1054
  struct section_list *sec, *csec;
 
1055
  const char *sval, **slist;
 
1056
  const char *filename = secfile_name(file);
 
1057
  const char **vnlist, **def_vnlist;
979
1058
  int *vblist, *def_vblist;
980
1059
 
981
 
  (void) check_ruleset_capabilities(file, "+1.9", filename);
 
1060
  (void) check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
982
1061
 
983
1062
  /*
984
1063
   * Load up expanded veteran system values.
985
1064
   */
986
 
  sec = secfile_get_secnames_prefix(file, UNIT_SECTION_PREFIX, &nval);
 
1065
  sec = secfile_sections_by_name_prefix(file, UNIT_SECTION_PREFIX);
 
1066
  nval = (NULL != sec ? section_list_size(sec) : 0);
987
1067
 
988
1068
#define CHECK_VETERAN_LIMIT(_count, _string)                            \
989
1069
if (_count > MAX_VET_LEVELS) {                                          \
990
1070
  ruleset_error(LOG_FATAL, "\"%s\": Too many " _string " entries (%d, max %d)", \
991
 
                filename, _count, MAX_VET_LEVELS);                      \
 
1071
                filename, (int) _count, MAX_VET_LEVELS);                \
992
1072
}
993
1073
 
994
1074
  /* level names */
1000
1080
    const int i = utype_index(u);
1001
1081
 
1002
1082
    vnlist = secfile_lookup_str_vec(file, &vet_levels,
1003
 
                                    "%s.veteran_names", sec[i]);
 
1083
                                    "%s.veteran_names",
 
1084
                                    section_name(section_list_get(sec, i)));
1004
1085
    CHECK_VETERAN_LIMIT(vet_levels, "veteran_names");
1005
1086
    if (vnlist) {
1006
1087
      /* unit has own veterancy settings */
1007
1088
      for (j = 0; j < vet_levels; j++) {
1008
 
        sz_strlcpy(u->veteran[j].name, vnlist[j]);
 
1089
        names_set(&u->veteran[j].name, vnlist[j], NULL);
1009
1090
      }
 
1091
      u->veteran_levels = vet_levels;
1010
1092
      free(vnlist);
1011
1093
    } else {
1012
1094
      /* apply defaults */  
1013
1095
      for (j = 0; j < vet_levels_default; j++) {
1014
 
        sz_strlcpy(u->veteran[j].name, def_vnlist[j]);
 
1096
        names_set(&u->veteran[j].name, def_vnlist[j], NULL);
1015
1097
      }
 
1098
      u->veteran_levels = vet_levels_default;
1016
1099
    }
1017
1100
    /* We check for this value to determine how many veteran levels
1018
1101
     * a unit type has */
1019
1102
    for (; j < MAX_VET_LEVELS; j++) {
1020
 
      u->veteran[j].name[0] = '\0';
 
1103
      names_set(&u->veteran[j].name, "", NULL);
1021
1104
    }
1022
1105
  } unit_type_iterate_end;
1023
1106
  free(def_vnlist);
1030
1113
    const int i = utype_index(u);
1031
1114
 
1032
1115
    vblist = secfile_lookup_int_vec(file, &vet_levels,
1033
 
                                    "%s.veteran_power_fact", sec[i]);
 
1116
                                    "%s.veteran_power_fact",
 
1117
                                    section_name(section_list_get(sec, i)));
1034
1118
    CHECK_VETERAN_LIMIT(vet_levels, "veteran_power_fact");
1035
1119
    if (vblist) {
1036
1120
      for (j = 0; j < vet_levels; j++) {
1083
1167
    const int i = utype_index(u);
1084
1168
 
1085
1169
    vblist = secfile_lookup_int_vec(file, &vet_levels,
1086
 
                        "%s.veteran_move_bonus", sec[i]);
 
1170
                                    "%s.veteran_move_bonus",
 
1171
                                    section_name(section_list_get(sec, i)));
1087
1172
    CHECK_VETERAN_LIMIT(vet_levels, "veteran_move_bonus");
1088
1173
    if (vblist) {
1089
1174
      for (j = 0; j < vet_levels; j++) {
1100
1185
    free(def_vblist);
1101
1186
  }
1102
1187
 
1103
 
  csec = secfile_get_secnames_prefix(file, UNIT_CLASS_SECTION_PREFIX, &nval);
 
1188
  csec = secfile_sections_by_name_prefix(file, UNIT_CLASS_SECTION_PREFIX);
 
1189
  nval = (NULL != csec ? section_list_size(csec) : 0);
1104
1190
 
1105
1191
  unit_class_iterate(ut) {
1106
1192
    int i = uclass_index(ut);
1107
1193
    char tmp[200] = "\0";
1108
 
    char *hut_str;
 
1194
    const char *hut_str;
 
1195
    const char *sec_name = section_name(section_list_get(csec, i));
1109
1196
 
1110
 
    mystrlcat(tmp, csec[i], 200);
1111
 
    mystrlcat(tmp, ".move_type", 200);
 
1197
    fc_strlcat(tmp, sec_name, 200);
 
1198
    fc_strlcat(tmp, ".move_type", 200);
1112
1199
    ut->move_type = lookup_move_type(file, tmp, filename);
1113
 
    ut->min_speed = SINGLE_MOVE * secfile_lookup_int(file, "%s.min_speed", csec[i]);
1114
 
    ut->hp_loss_pct = secfile_lookup_int(file,"%s.hp_loss_pct", csec[i]);
 
1200
    if (secfile_lookup_int(file, &ut->min_speed, "%s.min_speed", sec_name)) {
 
1201
      ut->min_speed *= SINGLE_MOVE;
 
1202
    } else {
 
1203
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
1204
    }
 
1205
    if (!secfile_lookup_int(file, &ut->hp_loss_pct,
 
1206
                            "%s.hp_loss_pct", sec_name)) {
 
1207
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
1208
    }
1115
1209
 
1116
 
    hut_str = secfile_lookup_str_default(file, "Normal", "%s.hut_behavior", csec[i]);
1117
 
    if (mystrcasecmp(hut_str, "Normal") == 0) {
 
1210
    hut_str = secfile_lookup_str_default(file, "Normal", "%s.hut_behavior", sec_name);
 
1211
    if (fc_strcasecmp(hut_str, "Normal") == 0) {
1118
1212
      ut->hut_behavior = HUT_NORMAL;
1119
 
    } else if (mystrcasecmp(hut_str, "Nothing") == 0) {
 
1213
    } else if (fc_strcasecmp(hut_str, "Nothing") == 0) {
1120
1214
      ut->hut_behavior = HUT_NOTHING;
1121
 
    } else if (mystrcasecmp(hut_str, "Frighten") == 0) {
 
1215
    } else if (fc_strcasecmp(hut_str, "Frighten") == 0) {
1122
1216
      ut->hut_behavior = HUT_FRIGHTEN;
1123
1217
    } else {
1124
1218
      ruleset_error(LOG_FATAL,
1130
1224
    }
1131
1225
 
1132
1226
    BV_CLR_ALL(ut->flags);
1133
 
    slist = secfile_lookup_str_vec(file, &nval, "%s.flags", csec[i]);
 
1227
    slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
1134
1228
    for(j = 0; j < nval; j++) {
1135
1229
      sval = slist[j];
1136
1230
      if(strcmp(sval,"") == 0) {
1137
 
        continue;
 
1231
        continue;
1138
1232
      }
1139
 
      ival = find_unit_class_flag_by_rule_name(sval);
1140
 
      if (ival == UCF_LAST) {
1141
 
        freelog(LOG_ERROR, "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
1142
 
                filename,
1143
 
                uclass_rule_name(ut),
1144
 
                sval);
1145
 
        ival = find_unit_flag_by_rule_name(sval);
 
1233
      ival = unit_class_flag_id_by_name(sval, fc_strcasecmp);
 
1234
      if (!unit_class_flag_id_is_valid(ival)) {
 
1235
        log_error("\"%s\" unit_class \"%s\": bad flag name \"%s\".",
 
1236
                  filename, uclass_rule_name(ut), sval);
 
1237
        ival = unit_flag_by_rule_name(sval);
1146
1238
        if (ival != F_LAST) {
1147
 
          freelog(LOG_ERROR, "\"%s\" unit_class \"%s\": unit_type flag!",
1148
 
                  filename,
1149
 
                  uclass_rule_name(ut));
 
1239
          log_error("\"%s\" unit_class \"%s\": unit_type flag!",
 
1240
                    filename, uclass_rule_name(ut));
1150
1241
        }
1151
1242
      } else if (ut->move_type == SEA_MOVING
1152
1243
                 && ( ival == UCF_ROAD_NATIVE || ival == UCF_RIVER_NATIVE)) {
1153
 
        freelog(LOG_ERROR, "\"%s\" unit_class \"%s\": cannot give \"%s\" flag"
1154
 
                " to sea moving unit",
1155
 
                filename,
1156
 
                uclass_rule_name(ut),
1157
 
                sval);
 
1244
        log_error("\"%s\" unit_class \"%s\": cannot give \"%s\" flag "
 
1245
                  "to sea moving unit",
 
1246
                  filename, uclass_rule_name(ut), sval);
1158
1247
      } else {
1159
1248
        BV_SET(ut->flags, ival);
1160
1249
      }
1166
1255
  /* Tech and Gov requirements */  
1167
1256
  unit_type_iterate(u) {
1168
1257
    const int i = utype_index(u);
 
1258
    const struct section *psection = section_list_get(sec, i);
1169
1259
 
1170
 
    u->require_advance = lookup_tech(file, sec[i], "tech_req", LOG_FATAL,
1171
 
                                     filename, u->name.vernacular);
1172
 
    if (section_file_lookup(file, "%s.gov_req", sec[i])) {
 
1260
    u->require_advance = lookup_tech(file, section_name(psection),
 
1261
                                     "tech_req", LOG_FATAL, filename,
 
1262
                                     rule_name(&u->name));
 
1263
    if (NULL != section_entry_by_name(psection, "gov_req")) {
1173
1264
      char tmp[200] = "\0";
1174
 
      mystrlcat(tmp, sec[i], 200);
1175
 
      mystrlcat(tmp, ".gov_req", 200);
 
1265
      fc_strlcat(tmp, section_name(psection), sizeof(tmp));
 
1266
      fc_strlcat(tmp, ".gov_req", sizeof(tmp));
1176
1267
      u->need_government = lookup_government(file, tmp, filename);
1177
1268
    } else {
1178
1269
      u->need_government = NULL; /* no requirement */
1181
1272
  
1182
1273
  unit_type_iterate(u) {
1183
1274
    const int i = utype_index(u);
 
1275
    const char *sec_name = section_name(section_list_get(sec, i));
1184
1276
 
1185
 
    u->obsoleted_by = lookup_unit_type(file, sec[i], "obsolete_by", LOG_ERROR,
1186
 
                                       filename, u->name.vernacular);
 
1277
    u->obsoleted_by = lookup_unit_type(file, sec_name, "obsolete_by",
 
1278
                                       LOG_ERROR, filename,
 
1279
                                       rule_name(&u->name));
 
1280
    u->converted_to = lookup_unit_type(file, sec_name, "convert_to",
 
1281
                                       LOG_ERROR, filename,
 
1282
                                       rule_name(&u->name));
1187
1283
  } unit_type_iterate_end;
1188
1284
 
1189
1285
  /* main stats: */
1190
1286
  unit_type_iterate(u) {
1191
1287
    const int i = utype_index(u);
1192
1288
    struct unit_class *pclass;
1193
 
 
1194
 
    u->need_improvement = lookup_building(file, sec[i], "impr_req", LOG_ERROR,
1195
 
                                          filename, u->name.vernacular);
1196
 
 
1197
 
    sval = secfile_lookup_str(file, "%s.class", sec[i]);
1198
 
    pclass = find_unit_class_by_rule_name(sval);
 
1289
    const char *sec_name = section_name(section_list_get(sec, i));
 
1290
    const char *string;
 
1291
 
 
1292
    u->need_improvement = lookup_building(file, sec_name, "impr_req",
 
1293
                                          LOG_ERROR, filename,
 
1294
                                          rule_name(&u->name));
 
1295
 
 
1296
    sval = secfile_lookup_str(file, "%s.class", sec_name);
 
1297
    pclass = unit_class_by_rule_name(sval);
1199
1298
    if (!pclass) {
1200
1299
      ruleset_error(LOG_FATAL,
1201
1300
                    "\"%s\" unit_type \"%s\":"
1207
1306
    u->uclass = pclass;
1208
1307
    
1209
1308
    sz_strlcpy(u->sound_move,
1210
 
               secfile_lookup_str_default(file, "-", "%s.sound_move",
1211
 
                                          sec[i]));
 
1309
               secfile_lookup_str_default(file, "-", "%s.sound_move",
 
1310
                                          sec_name));
1212
1311
    sz_strlcpy(u->sound_move_alt,
1213
 
               secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
1214
 
                                          sec[i]));
 
1312
               secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
 
1313
                                          sec_name));
1215
1314
    sz_strlcpy(u->sound_fight,
1216
 
               secfile_lookup_str_default(file, "-", "%s.sound_fight",
1217
 
                                          sec[i]));
 
1315
               secfile_lookup_str_default(file, "-", "%s.sound_fight",
 
1316
                                          sec_name));
1218
1317
    sz_strlcpy(u->sound_fight_alt,
1219
 
               secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
1220
 
                                          sec[i]));
1221
 
    
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",
 
1319
                                          sec_name));
 
1320
 
 
1321
    if ((string = secfile_lookup_str(file, "%s.graphic", sec_name))) {
 
1322
      sz_strlcpy(u->graphic_str, string);
 
1323
    } else {
 
1324
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
1325
    }
1224
1326
    sz_strlcpy(u->graphic_alt,
1225
 
               secfile_lookup_str_default(file, "-", "%s.graphic_alt", sec[i]));
1226
 
    
1227
 
    u->build_cost =
1228
 
      secfile_lookup_int(file,"%s.build_cost", sec[i]);
1229
 
    u->pop_cost =
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]);
1235
 
    u->move_rate =
1236
 
      SINGLE_MOVE*secfile_lookup_int(file,"%s.move_rate", sec[i]);
1237
 
    
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",
 
1328
                                          sec_name));
 
1329
 
 
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());
 
1353
    }
 
1354
    u->move_rate *= SINGLE_MOVE;
 
1355
 
1244
1356
    if (u->firepower <= 0) {
1245
1357
      ruleset_error(LOG_FATAL,
1246
1358
                    "\"%s\" unit_type \"%s\":"
1252
1364
                    utype_rule_name(u),
1253
1365
                    u->firepower);
1254
1366
    }
1255
 
    u->fuel = secfile_lookup_int(file,"%s.fuel", sec[i]);
1256
1367
 
1257
 
    u->happy_cost  = secfile_lookup_int(file, "%s.uk_happy", sec[i]);
1258
1368
    output_type_iterate(o) {
1259
 
      u->upkeep[o] = secfile_lookup_int_default(file, 0, "%s.uk_%s", sec[i],
1260
 
                                                get_output_identifier(o));
 
1369
      u->upkeep[o] = secfile_lookup_int_default(file, 0, "%s.uk_%s",
 
1370
                                                sec_name,
 
1371
                                                get_output_identifier(o));
1261
1372
    } output_type_iterate_end;
1262
1373
 
1263
 
    slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec[i]);
 
1374
    slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec_name);
1264
1375
    BV_CLR_ALL(u->cargo);
1265
1376
    for (j = 0; j < nval; j++) {
1266
 
      struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
 
1377
      struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
1267
1378
 
1268
 
      if (!class) {
 
1379
      if (!uclass) {
1269
1380
        ruleset_error(LOG_FATAL,
1270
1381
                      "\"%s\" unit_type \"%s\":"
1271
1382
                      "has unknown unit class %s as cargo.",
1274
1385
                      slist[j]);
1275
1386
      }
1276
1387
 
1277
 
      BV_SET(u->cargo, uclass_index(class));
 
1388
      BV_SET(u->cargo, uclass_index(uclass));
1278
1389
    }
1279
1390
    free(slist);
1280
1391
 
1281
 
    slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec[i]);
 
1392
    slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec_name);
1282
1393
    BV_CLR_ALL(u->targets);
1283
1394
    for (j = 0; j < nval; j++) {
1284
 
      struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
 
1395
      struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
1285
1396
 
1286
 
      if (!class) {
 
1397
      if (!uclass) {
1287
1398
        ruleset_error(LOG_FATAL,
1288
1399
                      "\"%s\" unit_type \"%s\":"
1289
1400
                      "has unknown unit class %s as target.",
1292
1403
                      slist[j]);
1293
1404
      }
1294
1405
 
1295
 
      BV_SET(u->targets, uclass_index(class));
 
1406
      BV_SET(u->targets, uclass_index(uclass));
1296
1407
    }
1297
1408
    free(slist);
1298
1409
 
1303
1414
      }
1304
1415
    } unit_class_iterate_end;
1305
1416
 
1306
 
    u->helptext = lookup_helptext(file, sec[i]);
 
1417
    u->helptext = lookup_strvec(file, sec_name, "helptext");
1307
1418
 
1308
1419
    u->paratroopers_range = secfile_lookup_int_default(file,
1309
 
        0, "%s.paratroopers_range", sec[i]);
 
1420
        0, "%s.paratroopers_range", sec_name);
1310
1421
    u->paratroopers_mr_req = SINGLE_MOVE * secfile_lookup_int_default(file,
1311
 
        0, "%s.paratroopers_mr_req", sec[i]);
 
1422
        0, "%s.paratroopers_mr_req", sec_name);
1312
1423
    u->paratroopers_mr_sub = SINGLE_MOVE * secfile_lookup_int_default(file,
1313
 
        0, "%s.paratroopers_mr_sub", sec[i]);
 
1424
        0, "%s.paratroopers_mr_sub", sec_name);
1314
1425
    u->bombard_rate = secfile_lookup_int_default(file,
1315
 
        0, "%s.bombard_rate", sec[i]);
1316
 
    u->city_size = secfile_lookup_int_default(file, 1, "%s.city_size", sec[i]);
 
1426
        0, "%s.bombard_rate", sec_name);
 
1427
    u->city_size = secfile_lookup_int_default(file,
 
1428
        1, "%s.city_size", sec_name);
1317
1429
  } unit_type_iterate_end;
1318
1430
  
1319
1431
  /* flags */
1321
1433
    const int i = utype_index(u);
1322
1434
 
1323
1435
    BV_CLR_ALL(u->flags);
1324
 
    assert(!utype_has_flag(u, F_LAST-1));
 
1436
    fc_assert(!utype_has_flag(u, F_LAST - 1));
1325
1437
 
1326
 
    slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec[i]);
 
1438
    slist = secfile_lookup_str_vec(file, &nval, "%s.flags",
 
1439
                                   section_name(section_list_get(sec, i)));
1327
1440
    for(j=0; j<nval; j++) {
1328
1441
      sval = slist[j];
1329
 
      if(strcmp(sval,"")==0) {
1330
 
        continue;
 
1442
      if (0 == strcmp(sval, "")) {
 
1443
        continue;
1331
1444
      }
1332
 
      ival = find_unit_flag_by_rule_name(sval);
1333
 
      if (ival==F_LAST) {
1334
 
        freelog(LOG_ERROR, "\"%s\" unit_type \"%s\": bad flag name \"%s\".",
1335
 
                filename,
1336
 
                utype_rule_name(u),
1337
 
                sval);
1338
 
        ival = find_unit_class_flag_by_rule_name(sval);
1339
 
        if (ival != UCF_LAST) {
1340
 
          freelog(LOG_ERROR, "\"%s\" unit_type \"%s\": unit_class flag!",
1341
 
                  filename,
1342
 
                  utype_rule_name(u));
 
1445
      ival = unit_flag_by_rule_name(sval);
 
1446
      if (F_LAST == ival) {
 
1447
        log_error("\"%s\" unit_type \"%s\": bad flag name \"%s\".",
 
1448
                  filename, utype_rule_name(u),  sval);
 
1449
        ival = unit_class_flag_id_by_name(sval, fc_strcasecmp);
 
1450
        if (unit_class_flag_id_is_valid(ival)) {
 
1451
          log_error("\"%s\" unit_type \"%s\": unit_class flag!",
 
1452
                    filename, utype_rule_name(u));
1343
1453
        }
1344
1454
      } else {
1345
1455
        BV_SET(u->flags, ival);
1346
1456
      }
1347
 
      assert(utype_has_flag(u, ival));
 
1457
      fc_assert(utype_has_flag(u, ival));
1348
1458
    }
1349
1459
    free(slist);
1350
1460
  } unit_type_iterate_end;
1355
1465
 
1356
1466
    BV_CLR_ALL(u->roles);
1357
1467
    
1358
 
    slist = secfile_lookup_str_vec(file, &nval, "%s.roles", sec[i] );
 
1468
    slist = secfile_lookup_str_vec(file, &nval, "%s.roles",
 
1469
                                   section_name(section_list_get(sec, i)));
1359
1470
    for(j=0; j<nval; j++) {
1360
1471
      sval = slist[j];
1361
1472
      if(strcmp(sval,"")==0) {
1362
1473
        continue;
1363
1474
      }
1364
 
      ival = find_unit_role_by_rule_name(sval);
 
1475
      ival = unit_role_by_rule_name(sval);
1365
1476
      if (ival==L_LAST) {
1366
 
        freelog(LOG_ERROR, "\"%s\" unit_type \"%s\": bad role name \"%s\".",
1367
 
                filename, utype_rule_name(u), sval);
 
1477
        log_error("\"%s\" unit_type \"%s\": bad role name \"%s\".",
 
1478
                  filename, utype_rule_name(u), sval);
1368
1479
      } else if ((ival == L_FERRYBOAT || ival == L_BARBARIAN_BOAT)
1369
1480
                 && u->uclass->move_type == LAND_MOVING) {
1370
 
        freelog(LOG_ERROR,
1371
 
                "\"%s\" unit_type \"%s\": role \"%s\" for land moving unit.",
1372
 
                filename, utype_rule_name(u), sval);
 
1481
        log_error( "\"%s\" unit_type \"%s\": role \"%s\" "
 
1482
                  "for land moving unit.",
 
1483
                  filename, utype_rule_name(u), sval);
1373
1484
      } else {
1374
1485
        BV_SET(u->roles, ival - L_FIRST);
1375
1486
      }
1376
 
      assert(utype_has_role(u, ival));
 
1487
      fc_assert(utype_has_role(u, ival));
1377
1488
    }
1378
1489
    free(slist);
1379
1490
  } unit_type_iterate_end;
1381
1492
  /* Some more consistency checking: */
1382
1493
  unit_type_iterate(u) {
1383
1494
    if (!valid_advance(u->require_advance)) {
1384
 
      freelog(LOG_ERROR,
1385
 
              "\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
1386
 
              filename,
1387
 
              utype_rule_name(u),
1388
 
              advance_rule_name(u->require_advance));
 
1495
      log_error("\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
 
1496
                filename, utype_rule_name(u),
 
1497
                advance_rule_name(u->require_advance));
1389
1498
      u->require_advance = A_NEVER;
1390
1499
    }
1391
1500
 
1416
1525
  if(num_role_units(L_FIRSTBUILD)==0) {
1417
1526
    ruleset_error(LOG_FATAL, "\"%s\": No role=firstbuild units?", filename);
1418
1527
  }
1419
 
  if (num_role_units(L_BARBARIAN) == 0 && game.info.barbarianrate > 0) {
 
1528
  if (0 == num_role_units(L_BARBARIAN)
 
1529
      && BARBS_DISABLED != game.server.barbarianrate) {
1420
1530
    ruleset_error(LOG_FATAL, "\"%s\": No role=barbarian units?", filename);
1421
1531
  }
1422
 
  if (num_role_units(L_BARBARIAN_LEADER) == 0 && game.info.barbarianrate > 0) {
 
1532
  if (0 == num_role_units(L_BARBARIAN_LEADER)
 
1533
      && BARBS_DISABLED != game.server.barbarianrate) {
1423
1534
    ruleset_error(LOG_FATAL, "\"%s\": No role=barbarian leader units?", filename);
1424
1535
  }
1425
 
  if (num_role_units(L_BARBARIAN_BUILD) == 0 && game.info.barbarianrate > 0) {
 
1536
  if (0 == num_role_units(L_BARBARIAN_BUILD)
 
1537
      && BARBS_DISABLED != game.server.barbarianrate) {
1426
1538
    ruleset_error(LOG_FATAL, "\"%s\": No role=barbarian build units?", filename);
1427
1539
  }
1428
 
  if (num_role_units(L_BARBARIAN_BOAT) == 0 && game.info.barbarianrate > 0) {
 
1540
  if (0 == num_role_units(L_BARBARIAN_BOAT)
 
1541
      && BARBS_DISABLED != game.server.barbarianrate) {
1429
1542
    ruleset_error(LOG_FATAL, "\"%s\": No role=barbarian ship units?", filename);
1430
1543
  } else if (num_role_units(L_BARBARIAN_BOAT) > 0) {
1431
1544
    u = get_role_unit(L_BARBARIAN_BOAT,0);
1436
1549
                    utype_rule_name(u));
1437
1550
    }
1438
1551
  }
1439
 
  if (num_role_units(L_BARBARIAN_SEA) == 0 && game.info.barbarianrate > 0) {
 
1552
  if (0 == num_role_units(L_BARBARIAN_SEA)
 
1553
      && BARBS_DISABLED != game.server.barbarianrate) {
1440
1554
    ruleset_error(LOG_FATAL, "\"%s\": No role=sea raider barbarian units?",
1441
1555
                  filename);
1442
1556
  }
1443
1557
 
1444
1558
  update_simple_ai_types();
1445
1559
 
1446
 
  free(csec);
1447
 
  free(sec);
1448
 
  section_file_check_unused(file, filename);
1449
 
  section_file_free(file);
 
1560
  section_list_destroy(csec);
 
1561
  section_list_destroy(sec);
 
1562
  secfile_check_unused(file);
 
1563
  secfile_destroy(file);
1450
1564
}
1451
1565
 
1452
1566
/**************************************************************************
1454
1568
**************************************************************************/
1455
1569
static void load_building_names(struct section_file *file)
1456
1570
{
1457
 
  char **sec;
1458
 
  int i, nval;
1459
 
  const char *filename = secfile_filename(file);
 
1571
  struct section_list *sec;
 
1572
  int i, nval = 0;
 
1573
  const char *filename = secfile_name(file);
1460
1574
 
1461
 
  (void) section_file_lookup(file, "datafile.description");     /* unused */
 
1575
  (void) secfile_entry_by_path(file, "datafile.description");   /* unused */
1462
1576
 
1463
1577
  /* The names: */
1464
 
  sec = secfile_get_secnames_prefix(file, BUILDING_SECTION_PREFIX, &nval);
1465
 
  freelog(LOG_VERBOSE, "%d improvement types (including possibly unused)", nval);
1466
 
  if (nval == 0) {
 
1578
  sec = secfile_sections_by_name_prefix(file, BUILDING_SECTION_PREFIX);
 
1579
  if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1467
1580
    ruleset_error(LOG_FATAL, "\"%s\": No improvements?!?", filename);
1468
1581
  }
 
1582
  log_verbose("%d improvement types (including possibly unused)", nval);
1469
1583
  if (nval > B_LAST) {
1470
1584
    ruleset_error(LOG_FATAL, "\"%s\": Too many improvements (%d, max %d)",
1471
1585
                  filename, nval, B_LAST);
1474
1588
  game.control.num_impr_types = nval;
1475
1589
 
1476
1590
  for (i = 0; i < nval; i++) {
1477
 
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
1478
1591
    struct impr_type *b = improvement_by_number(i);
1479
 
 
1480
 
    name_strlcpy(b->name.vernacular, name);
1481
 
    b->name.translated = NULL;
 
1592
    ruleset_load_names(&b->name, file, section_name(section_list_get(sec, i)));
1482
1593
  }
1483
1594
 
1484
 
  free(sec);
 
1595
  section_list_destroy(sec);
1485
1596
}
1486
1597
 
1487
1598
/**************************************************************************
1489
1600
**************************************************************************/
1490
1601
static void load_ruleset_buildings(struct section_file *file)
1491
1602
{
1492
 
  char **sec, *item;
 
1603
  struct section_list *sec;
 
1604
  const char *item;
1493
1605
  int i, nval;
1494
 
  const char *filename = secfile_filename(file);
1495
 
 
1496
 
  (void) check_ruleset_capabilities(file, "+1.10.1", filename);
1497
 
 
1498
 
  sec = secfile_get_secnames_prefix(file, BUILDING_SECTION_PREFIX, &nval);
 
1606
  const char *filename = secfile_name(file);
 
1607
 
 
1608
  (void) check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
 
1609
 
 
1610
  sec = secfile_sections_by_name_prefix(file, BUILDING_SECTION_PREFIX);
 
1611
  nval = (NULL != sec ? section_list_size(sec) : 0);
1499
1612
 
1500
1613
  for (i = 0; i < nval; i++) {
1501
1614
    struct impr_type *b = improvement_by_number(i);
 
1615
    const char *sec_name = section_name(section_list_get(sec, i));
1502
1616
    struct requirement_vector *reqs =
1503
 
      lookup_req_list(file, sec[i], "reqs",
 
1617
      lookup_req_list(file, sec_name, "reqs",
1504
1618
                      improvement_rule_name(b));
1505
 
    char *sval, **slist;
1506
 
    int j, nflags, ival;
 
1619
    const char *sval, **slist;
 
1620
    int j, ival;
 
1621
    size_t nflags;
1507
1622
 
1508
 
    item = secfile_lookup_str(file, "%s.genus", sec[i]);
1509
 
    b->genus = find_genus_by_rule_name(item);
1510
 
    if (b->genus == IG_LAST) {
1511
 
      ruleset_error(LOG_FATAL,
1512
 
                    "\"%s\" improvement \"%s\": couldn't match genus \"%s\".",
1513
 
                    filename,
1514
 
                    improvement_rule_name(b),
1515
 
                    item);
 
1623
    item = secfile_lookup_str(file, "%s.genus", sec_name);
 
1624
    b->genus = impr_genus_id_by_name(item, fc_strcasecmp);
 
1625
    if (!impr_genus_id_is_valid(b->genus)) {
 
1626
      ruleset_error(LOG_FATAL, "\"%s\" improvement \"%s\": couldn't match "
 
1627
                               "genus \"%s\".", filename,
 
1628
                    improvement_rule_name(b), item);
1516
1629
    }
1517
1630
 
1518
 
    slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec[i]);
1519
 
    b->flags = 0;
 
1631
    slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec_name);
 
1632
    BV_CLR_ALL(b->flags);
1520
1633
 
1521
1634
    for(j=0; j<nflags; j++) {
1522
1635
      sval = slist[j];
1523
1636
      if(strcmp(sval,"")==0) {
1524
1637
        continue;
1525
1638
      }
1526
 
      ival = find_improvement_flag_by_rule_name(sval);
1527
 
      if (ival==IF_LAST) {
1528
 
        freelog(LOG_ERROR,
1529
 
                "\"%s\" improvement \"%s\": bad flag name \"%s\".",
1530
 
                filename,
1531
 
                improvement_rule_name(b),
1532
 
                sval);
 
1639
      ival = impr_flag_id_by_name(sval, fc_strcasecmp);
 
1640
      if (!impr_flag_id_is_valid(ival)) {
 
1641
        log_error("\"%s\" improvement \"%s\": bad flag name \"%s\".",
 
1642
                  filename, improvement_rule_name(b), sval);
1533
1643
      } else {
1534
 
        b->flags |= (1<<ival);
 
1644
        BV_SET(b->flags, ival);
1535
1645
      }
1536
1646
    }
1537
1647
    free(slist);
1538
1648
 
1539
1649
    requirement_vector_copy(&b->reqs, reqs);
1540
1650
 
1541
 
    b->obsolete_by = lookup_tech(file, sec[i], "obsolete_by", LOG_ERROR,
1542
 
                                 filename, b->name.vernacular);
 
1651
    b->obsolete_by = lookup_tech(file, sec_name, "obsolete_by", LOG_ERROR,
 
1652
                                 filename, rule_name(&b->name));
1543
1653
    if (advance_by_number(A_NONE) == b->obsolete_by) {
1544
1654
      /* 
1545
1655
       * The ruleset can specify "None" for a never-obsoleted
1551
1661
      b->obsolete_by = A_NEVER;
1552
1662
    }
1553
1663
 
1554
 
    b->replaced_by = lookup_building(file, sec[i], "replaced_by", LOG_ERROR,
1555
 
                                     filename, b->name.vernacular);
1556
 
 
1557
 
    b->build_cost = secfile_lookup_int(file, "%s.build_cost", sec[i]);
1558
 
 
1559
 
    b->upkeep = secfile_lookup_int(file, "%s.upkeep", sec[i]);
1560
 
 
1561
 
    b->sabotage = secfile_lookup_int(file, "%s.sabotage", sec[i]);
 
1664
    b->replaced_by = lookup_building(file, sec_name, "replaced_by",
 
1665
                                     LOG_ERROR, filename,
 
1666
                                     rule_name(&b->name));
 
1667
 
 
1668
    if (!secfile_lookup_int(file, &b->build_cost,
 
1669
                            "%s.build_cost", sec_name)
 
1670
        || !secfile_lookup_int(file, &b->upkeep,
 
1671
                               "%s.upkeep", sec_name)
 
1672
        || !secfile_lookup_int(file, &b->sabotage,
 
1673
                               "%s.sabotage", sec_name)) {
 
1674
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
1675
    }
1562
1676
 
1563
1677
    sz_strlcpy(b->graphic_str,
1564
 
               secfile_lookup_str_default(file, "-", "%s.graphic", sec[i]));
 
1678
               secfile_lookup_str_default(file, "-",
 
1679
                                          "%s.graphic", sec_name));
1565
1680
    sz_strlcpy(b->graphic_alt,
1566
 
            secfile_lookup_str_default(file, "-", "%s.graphic_alt", sec[i]));
 
1681
               secfile_lookup_str_default(file, "-",
 
1682
                                          "%s.graphic_alt", sec_name));
1567
1683
 
1568
1684
    sz_strlcpy(b->soundtag,
1569
 
               secfile_lookup_str_default(file, "-", "%s.sound", sec[i]));
 
1685
               secfile_lookup_str_default(file, "-",
 
1686
                                          "%s.sound", sec_name));
1570
1687
    sz_strlcpy(b->soundtag_alt,
1571
 
               secfile_lookup_str_default(file, "-", "%s.sound_alt",
1572
 
                                          sec[i]));
1573
 
    b->helptext = lookup_helptext(file, sec[i]);
 
1688
               secfile_lookup_str_default(file, "-",
 
1689
                                          "%s.sound_alt", sec_name));
 
1690
    b->helptext = lookup_strvec(file, sec_name, "helptext");
1574
1691
 
1575
1692
    b->allows_units = FALSE;
1576
1693
    unit_type_iterate(ut) {
1586
1703
    if (valid_improvement(b)) {
1587
1704
      if (A_NEVER != b->obsolete_by
1588
1705
          && !valid_advance(b->obsolete_by)) {
1589
 
        freelog(LOG_ERROR,
1590
 
                "\"%s\" improvement \"%s\": obsoleted by removed tech \"%s\".",
1591
 
                filename,
1592
 
                improvement_rule_name(b),
1593
 
                advance_rule_name(b->obsolete_by));
1594
 
        b->obsolete_by = A_NEVER;
 
1706
        log_error("\"%s\" improvement \"%s\": obsoleted by "
 
1707
                  "removed tech \"%s\".",
 
1708
                  filename, improvement_rule_name(b),
 
1709
                  advance_rule_name(b->obsolete_by));
 
1710
        b->obsolete_by = A_NEVER;
1595
1711
      }
1596
1712
    }
1597
1713
  } improvement_iterate_end;
1598
1714
 
1599
 
  free(sec);
1600
 
  section_file_check_unused(file, filename);
1601
 
  section_file_free(file);
 
1715
  section_list_destroy(sec);
 
1716
  secfile_check_unused(file);
 
1717
  secfile_destroy(file);
1602
1718
}
1603
1719
 
1604
1720
/**************************************************************************
1606
1722
**************************************************************************/
1607
1723
static void load_terrain_names(struct section_file *file)
1608
1724
{
1609
 
  int nval;
1610
 
  char **sec;
1611
 
  const char *filename = secfile_filename(file);
 
1725
  int nval = 0;
 
1726
  struct section_list *sec;
 
1727
  const char *filename = secfile_name(file);
1612
1728
 
1613
 
  (void) section_file_lookup(file, "datafile.description");     /* unused */
 
1729
  (void) secfile_entry_by_path(file, "datafile.description");   /* unused */
1614
1730
 
1615
1731
  /* terrain names */
1616
1732
 
1617
 
  sec = secfile_get_secnames_prefix(file, TERRAIN_SECTION_PREFIX, &nval);
1618
 
  if (nval == 0) {
 
1733
  sec = secfile_sections_by_name_prefix(file, TERRAIN_SECTION_PREFIX);
 
1734
  if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1619
1735
    ruleset_error(LOG_FATAL, "\"%s\": ruleset doesn't have any terrains.",
1620
1736
                  filename);
1621
1737
  }
1622
1738
  if (nval > MAX_NUM_TERRAINS) {
1623
1739
    ruleset_error(LOG_FATAL, "\"%s\": Too many terrains (%d, max %d)",
1624
 
                  filename,
1625
 
                  nval,
1626
 
                  MAX_NUM_TERRAINS);
 
1740
                  filename, nval, MAX_NUM_TERRAINS);
1627
1741
  }
1628
1742
  game.control.terrain_count = nval;
1629
1743
 
1635
1749
 
1636
1750
  terrain_type_iterate(pterrain) {
1637
1751
    const int i = terrain_index(pterrain);
1638
 
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
 
1752
    const char *sec_name = section_name(section_list_get(sec, i));
 
1753
    ruleset_load_names(&pterrain->name, file, sec_name);
1639
1754
 
1640
 
    name_strlcpy(pterrain->name.vernacular, name);
1641
 
    if (0 == strcmp(pterrain->name.vernacular, "unused")) {
1642
 
      pterrain->name.vernacular[0] = '\0';
 
1755
    if (0 == strcmp(rule_name(&pterrain->name), "unused")) {
 
1756
      name_set(&pterrain->name, "");
1643
1757
    }
1644
 
    pterrain->name.translated = NULL;
1645
1758
 
1646
 
    section_strlcpy(&terrain_sections[i * MAX_SECTION_LABEL], sec[i]);
 
1759
    section_strlcpy(&terrain_sections[i * MAX_SECTION_LABEL], sec_name);
1647
1760
  } terrain_type_iterate_end;
1648
1761
 
1649
 
  free(sec);
 
1762
  section_list_destroy(sec);
1650
1763
 
1651
1764
  /* resource names */
1652
1765
 
1653
 
  sec = secfile_get_secnames_prefix(file, RESOURCE_SECTION_PREFIX, &nval);
 
1766
  sec = secfile_sections_by_name_prefix(file, RESOURCE_SECTION_PREFIX);
 
1767
  nval = (NULL != sec ? section_list_size(sec) : 0);
1654
1768
  if (nval > MAX_NUM_RESOURCES) {
1655
1769
    ruleset_error(LOG_FATAL, "\"%s\": Too many resources (%d, max %d)",
1656
 
                  filename,
1657
 
                  nval,
1658
 
                  MAX_NUM_RESOURCES);
 
1770
                  filename, nval, MAX_NUM_RESOURCES);
1659
1771
  }
1660
1772
  game.control.resource_count = nval;
1661
1773
 
1667
1779
 
1668
1780
  resource_type_iterate(presource) {
1669
1781
    const int i = resource_index(presource);
1670
 
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
 
1782
    const char *sec_name = section_name(section_list_get(sec, i));
 
1783
    ruleset_load_names(&presource->name, file, sec_name);
1671
1784
 
1672
 
    name_strlcpy(presource->name.vernacular, name);
1673
 
    if (0 == strcmp(presource->name.vernacular, "unused")) {
1674
 
      presource->name.vernacular[0] = '\0';
 
1785
    if (0 == strcmp(rule_name(&presource->name), "unused")) {
 
1786
      name_set(&presource->name, "");
1675
1787
    }
1676
 
    presource->name.translated = NULL;
1677
1788
 
1678
 
    section_strlcpy(&resource_sections[i * MAX_SECTION_LABEL], sec[i]);
 
1789
    section_strlcpy(&resource_sections[i * MAX_SECTION_LABEL], sec_name);
1679
1790
  } resource_type_iterate_end;
1680
1791
 
1681
 
  free(sec);
 
1792
  if (NULL != sec) {
 
1793
    section_list_destroy(sec);
 
1794
  }
1682
1795
 
1683
1796
  /* base names */
1684
1797
 
1685
 
  sec = secfile_get_secnames_prefix(file, BASE_SECTION_PREFIX, &nval);
 
1798
  sec = secfile_sections_by_name_prefix(file, BASE_SECTION_PREFIX);
 
1799
  nval = (NULL != sec ? section_list_size(sec) : 0);
1686
1800
  if (nval > MAX_BASE_TYPES) {
1687
1801
    ruleset_error(LOG_FATAL, "\"%s\": Too many base types (%d, max %d)",
1688
 
                  filename,
1689
 
                  nval,
1690
 
                  MAX_BASE_TYPES);
 
1802
                  filename, nval, MAX_BASE_TYPES);
1691
1803
  }
1692
1804
  game.control.num_base_types = nval;
1693
1805
 
1698
1810
 
1699
1811
  base_type_iterate(pbase) {
1700
1812
    const int i = base_index(pbase);
1701
 
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
1702
 
 
1703
 
    name_strlcpy(pbase->name.vernacular, name);
1704
 
    pbase->name.translated = NULL;
1705
 
 
1706
 
    section_strlcpy(&base_sections[i * MAX_SECTION_LABEL], sec[i]);
 
1813
    const char *sec_name = section_name(section_list_get(sec, i));
 
1814
    ruleset_load_names(&pbase->name, file, sec_name);
 
1815
    section_strlcpy(&base_sections[i * MAX_SECTION_LABEL], sec_name);
1707
1816
  } base_type_iterate_end;
1708
1817
 
1709
 
  free(sec);
 
1818
  if (NULL != sec) {
 
1819
    section_list_destroy(sec);
 
1820
  }
1710
1821
}
1711
1822
 
1712
1823
/**************************************************************************
1714
1825
**************************************************************************/
1715
1826
static void load_ruleset_terrain(struct section_file *file)
1716
1827
{
1717
 
  int nval;
 
1828
  struct strvec *psv;
 
1829
  size_t nval;
1718
1830
  int j;
1719
 
  char **res;
1720
 
  const char *filename = secfile_filename(file);
 
1831
  const char **res;
 
1832
  const char *filename = secfile_name(file);
1721
1833
  /* char *datafile_options = */ (void)
1722
 
    check_ruleset_capabilities(file, TERRAIN_CAPABILITY, filename);
 
1834
    check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
1723
1835
 
1724
1836
  /* options */
1725
1837
  terrain_control.may_road =
1751
1863
    secfile_lookup_int_default(file, 50, "parameters.river_defense_bonus");
1752
1864
  terrain_control.river_trade_incr =
1753
1865
    secfile_lookup_int_default(file, 1, "parameters.river_trade_incr");
1754
 
  {
1755
 
    char *s = secfile_lookup_str_default(file, "",
1756
 
      "parameters.river_help_text");
1757
 
    sz_strlcpy(terrain_control.river_help_text, s);
 
1866
 
 
1867
  psv = lookup_strvec(file, "parameters", "river_help_text");
 
1868
  PACKET_STRVEC_COMPUTE(terrain_control.river_help_text, psv);
 
1869
  if (NULL != psv) {
 
1870
    strvec_destroy(psv);
1758
1871
  }
1759
1872
 
1760
1873
  terrain_control.road_superhighway_trade_bonus =
1776
1889
  /* terrain details */
1777
1890
 
1778
1891
  terrain_type_iterate(pterrain) {
1779
 
    char **slist;
 
1892
    const char **slist;
1780
1893
    const int i = terrain_index(pterrain);
1781
1894
    const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
1782
1895
 
1807
1920
      }
1808
1921
    }
1809
1922
 
1810
 
    pterrain->movement_cost
1811
 
      = secfile_lookup_int(file, "%s.movement_cost", tsection);
1812
 
    pterrain->defense_bonus
1813
 
      = secfile_lookup_int(file, "%s.defense_bonus", tsection);
 
1923
    if (!secfile_lookup_int(file, &pterrain->movement_cost,
 
1924
                            "%s.movement_cost", tsection)
 
1925
        || !secfile_lookup_int(file, &pterrain->defense_bonus,
 
1926
                               "%s.defense_bonus", tsection)) {
 
1927
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
1928
    }
1814
1929
 
1815
1930
    output_type_iterate(o) {
1816
1931
      pterrain->output[o]
1827
1942
    free(res);
1828
1943
    res = NULL;
1829
1944
 
1830
 
    pterrain->road_trade_incr
1831
 
      = secfile_lookup_int(file, "%s.road_trade_incr", tsection);
1832
 
    pterrain->road_time = secfile_lookup_int(file, "%s.road_time", tsection);
 
1945
    if (!secfile_lookup_int(file, &pterrain->road_trade_incr,
 
1946
                            "%s.road_trade_incr", tsection)
 
1947
        || !secfile_lookup_int(file, &pterrain->road_time,
 
1948
                               "%s.road_time", tsection)) {
 
1949
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
1950
    }
1833
1951
 
1834
1952
    pterrain->irrigation_result
1835
1953
      = lookup_terrain(file, "irrigation_result", pterrain);
1836
 
    pterrain->irrigation_food_incr
1837
 
      = secfile_lookup_int(file, "%s.irrigation_food_incr", tsection);
1838
 
    pterrain->irrigation_time
1839
 
      = secfile_lookup_int(file, "%s.irrigation_time", tsection);
 
1954
    if (!secfile_lookup_int(file, &pterrain->irrigation_food_incr,
 
1955
                            "%s.irrigation_food_incr", tsection)
 
1956
        || !secfile_lookup_int(file, &pterrain->irrigation_time,
 
1957
                               "%s.irrigation_time", tsection)) {
 
1958
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
1959
    }
1840
1960
 
1841
1961
    pterrain->mining_result
1842
1962
      = lookup_terrain(file, "mining_result", pterrain);
1843
 
    pterrain->mining_shield_incr
1844
 
      = secfile_lookup_int(file, "%s.mining_shield_incr", tsection);
1845
 
    pterrain->mining_time
1846
 
      = secfile_lookup_int(file, "%s.mining_time", tsection);
 
1963
    if (!secfile_lookup_int(file, &pterrain->mining_shield_incr,
 
1964
                            "%s.mining_shield_incr", tsection)
 
1965
        || !secfile_lookup_int(file, &pterrain->mining_time,
 
1966
                               "%s.mining_time", tsection)) {
 
1967
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
1968
    }
1847
1969
 
1848
1970
    pterrain->transform_result
1849
1971
      = lookup_terrain(file, "transform_result", pterrain);
1850
 
    pterrain->transform_time
1851
 
      = secfile_lookup_int(file, "%s.transform_time", tsection);
 
1972
    if (!secfile_lookup_int(file, &pterrain->transform_time,
 
1973
                            "%s.transform_time", tsection)) {
 
1974
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
1975
    }
1852
1976
    pterrain->rail_time
1853
1977
      = secfile_lookup_int_default(file, 3, "%s.rail_time", tsection);
1854
1978
    pterrain->clean_pollution_time
1869
1993
    BV_CLR_ALL(pterrain->flags);
1870
1994
    for (j = 0; j < nval; j++) {
1871
1995
      const char *sval = slist[j];
1872
 
      enum terrain_flag_id flag = find_terrain_flag_by_rule_name(sval);
 
1996
      enum terrain_flag_id flag
 
1997
        = terrain_flag_id_by_name(sval, fc_strcasecmp);
1873
1998
 
1874
 
      if (flag == TER_LAST) {
 
1999
      if (!terrain_flag_id_is_valid(flag)) {
1875
2000
        ruleset_error(LOG_FATAL, "\"%s\" [%s] has unknown flag \"%s\".",
1876
2001
                      filename, tsection, sval);
1877
2002
      } else {
1880
2005
    }
1881
2006
    free(slist);
1882
2007
 
1883
 
    for (j = 0; j < MG_LAST; j++) {
1884
 
      const char *mg_names[] = {
1885
 
        "mountainous", "green", "foliage",
1886
 
        "tropical", "temperate", "cold", "frozen",
1887
 
        "wet", "dry", "ocean_depth"
1888
 
      };
1889
 
      assert(ARRAY_SIZE(mg_names) == MG_LAST);
1890
 
 
1891
 
      pterrain->property[j] = secfile_lookup_int_default(file, 0,
1892
 
                                                         "%s.property_%s",
1893
 
                                                         tsection, mg_names[j]);
 
2008
    {
 
2009
      enum mapgen_terrain_property mtp;
 
2010
      for (mtp = mapgen_terrain_property_begin();
 
2011
           mtp != mapgen_terrain_property_end();
 
2012
           mtp = mapgen_terrain_property_next(mtp)) {
 
2013
        pterrain->property[mtp]
 
2014
          = secfile_lookup_int_default(file, 0, "%s.property_%s", tsection,
 
2015
                                       mapgen_terrain_property_name(mtp));
 
2016
      }
1894
2017
    }
1895
2018
 
1896
2019
    slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
1897
2020
    BV_CLR_ALL(pterrain->native_to);
1898
2021
    for (j = 0; j < nval; j++) {
1899
 
      struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
 
2022
      struct unit_class *class = unit_class_by_rule_name(slist[j]);
1900
2023
 
1901
2024
      if (!class) {
1902
2025
        ruleset_error(LOG_FATAL,
1916
2039
    }
1917
2040
    free(slist);
1918
2041
 
1919
 
    pterrain->helptext = lookup_helptext(file, tsection);
 
2042
    pterrain->helptext = lookup_strvec(file, tsection, "helptext");
1920
2043
  } terrain_type_iterate_end;
1921
2044
 
1922
2045
  /* resource details */
1969
2092
  base_type_iterate(pbase) {
1970
2093
    const char *section = &base_sections[base_index(pbase) * MAX_SECTION_LABEL];
1971
2094
    int j;
1972
 
    char **slist;
 
2095
    const char **slist;
1973
2096
    struct requirement_vector *reqs;
1974
 
    char *gui_str;
 
2097
    const char *gui_str;
1975
2098
 
1976
2099
    pbase->buildable = secfile_lookup_bool_default(file, TRUE,
1977
2100
                                                  "%s.buildable", section);
1993
2116
    slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
1994
2117
    BV_CLR_ALL(pbase->native_to);
1995
2118
    for (j = 0; j < nval; j++) {
1996
 
      struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
 
2119
      struct unit_class *class = unit_class_by_rule_name(slist[j]);
1997
2120
 
1998
2121
      if (!class) {
1999
2122
        ruleset_error(LOG_FATAL,
2016
2139
                    gui_str);
2017
2140
    }
2018
2141
 
2019
 
    pbase->build_time = secfile_lookup_int(file, "%s.build_time", section);
 
2142
    if (!secfile_lookup_int(file, &pbase->build_time,
 
2143
                            "%s.build_time", section)) {
 
2144
      ruleset_error(LOG_FATAL, "%s", secfile_error());
 
2145
    }
2020
2146
    pbase->border_sq  = secfile_lookup_int_default(file, -1, "%s.border_sq",
2021
2147
                                                   section);
2022
2148
    pbase->vision_main_sq   = secfile_lookup_int_default(file, -1,
2050
2176
    slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
2051
2177
    for (j = 0; j < nval; j++) {
2052
2178
      const char *sval = slist[j];
2053
 
      struct base_type *pbase2 = find_base_type_by_rule_name(sval);
 
2179
      struct base_type *pbase2 = base_type_by_rule_name(sval);
2054
2180
 
2055
2181
      if (pbase2 == NULL) {
2056
2182
        ruleset_error(LOG_FATAL, "\"%s\" base \"%s\": unknown conflict base \"%s\".",
2078
2204
      } base_type_iterate_end;
2079
2205
    }
2080
2206
 
 
2207
    pbase->helptext = lookup_strvec(file, section, "helptext");
2081
2208
  } base_type_iterate_end;
2082
2209
 
2083
 
  section_file_check_unused(file, filename);
2084
 
  section_file_free(file);
 
2210
  secfile_check_unused(file);
 
2211
  secfile_destroy(file);
2085
2212
}
2086
2213
 
2087
2214
/**************************************************************************
2089
2216
**************************************************************************/
2090
2217
static void load_government_names(struct section_file *file)
2091
2218
{
2092
 
  int nval;
2093
 
  char **sec;
2094
 
  const char *filename = secfile_filename(file);
2095
 
 
2096
 
  (void) section_file_lookup(file, "datafile.description");     /* unused */
2097
 
 
2098
 
  sec = secfile_get_secnames_prefix(file, GOVERNMENT_SECTION_PREFIX, &nval);
2099
 
  if (nval == 0) {
 
2219
  int nval = 0;
 
2220
  struct section_list *sec;
 
2221
  const char *filename = secfile_name(file);
 
2222
 
 
2223
  (void) secfile_entry_by_path(file, "datafile.description");   /* unused */
 
2224
 
 
2225
  sec = secfile_sections_by_name_prefix(file, GOVERNMENT_SECTION_PREFIX);
 
2226
  if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2100
2227
    ruleset_error(LOG_FATAL, "\"%s\": No governments?!?", filename);
2101
2228
  } else if(nval > G_MAGIC) {
2102
2229
    /* upper limit is really about 255 for 8-bit id values, but
2109
2236
 
2110
2237
  /* Government names are needed early so that get_government_by_name will
2111
2238
   * work. */
2112
 
  government_iterate(gov) {
2113
 
    char *name = secfile_lookup_str(file, "%s.name",
2114
 
                                    sec[government_index(gov)]);
2115
 
 
2116
 
    name_strlcpy(gov->name.vernacular, name);
2117
 
    gov->name.translated = NULL;
2118
 
  } government_iterate_end;
2119
 
  free(sec);
 
2239
  governments_iterate(gov) {
 
2240
    const char *sec_name =
 
2241
        section_name(section_list_get(sec, government_index(gov)));
 
2242
    ruleset_load_names(&gov->name, file, sec_name);
 
2243
  } governments_iterate_end;
 
2244
  section_list_destroy(sec);
2120
2245
}
2121
2246
 
2122
2247
/**************************************************************************
2125
2250
static void load_ruleset_governments(struct section_file *file)
2126
2251
{
2127
2252
  int nval;
2128
 
  char **sec;
2129
 
  const char *filename = secfile_filename(file);
2130
 
 
2131
 
  (void) check_ruleset_capabilities(file, "+1.9", filename);
2132
 
 
2133
 
  sec = secfile_get_secnames_prefix(file, GOVERNMENT_SECTION_PREFIX, &nval);
 
2253
  struct section_list *sec;
 
2254
  const char *filename = secfile_name(file);
 
2255
 
 
2256
  (void) check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
 
2257
 
 
2258
  sec = secfile_sections_by_name_prefix(file, GOVERNMENT_SECTION_PREFIX);
 
2259
  nval = (NULL != sec ? section_list_size(sec) : 0);
2134
2260
 
2135
2261
  game.government_during_revolution
2136
2262
    = lookup_government(file, "governments.during_revolution", filename);
2138
2264
    government_number(game.government_during_revolution);
2139
2265
 
2140
2266
  /* easy ones: */
2141
 
  government_iterate(g) {
 
2267
  governments_iterate(g) {
2142
2268
    const int i = government_index(g);
 
2269
    const char *sec_name = section_name(section_list_get(sec, i));
2143
2270
    struct requirement_vector *reqs =
2144
 
      lookup_req_list(file, sec[i], "reqs", government_rule_name(g));
 
2271
      lookup_req_list(file, sec_name, "reqs", government_rule_name(g));
2145
2272
 
2146
 
    if (section_file_lookup(file, "%s.ai_better", sec[i])) {
 
2273
    if (NULL != secfile_entry_lookup(file, "%s.ai_better", sec_name)) {
2147
2274
      char entry[100];
2148
2275
 
2149
 
      my_snprintf(entry, sizeof(entry), "%s.ai_better", sec[i]);
 
2276
      fc_snprintf(entry, sizeof(entry), "%s.ai_better", sec_name);
2150
2277
      g->ai.better = lookup_government(file, entry, filename);
2151
2278
    } else {
2152
2279
      g->ai.better = NULL;
2154
2281
    requirement_vector_copy(&g->reqs, reqs);
2155
2282
    
2156
2283
    sz_strlcpy(g->graphic_str,
2157
 
               secfile_lookup_str(file, "%s.graphic", sec[i]));
 
2284
               secfile_lookup_str(file, "%s.graphic", sec_name));
2158
2285
    sz_strlcpy(g->graphic_alt,
2159
 
               secfile_lookup_str(file, "%s.graphic_alt", sec[i]));
2160
 
 
2161
 
    g->helptext = lookup_helptext(file, sec[i]);
2162
 
  } government_iterate_end;
2163
 
 
2164
 
  
 
2286
               secfile_lookup_str(file, "%s.graphic_alt", sec_name));
 
2287
 
 
2288
    g->helptext = lookup_strvec(file, sec_name, "helptext");
 
2289
  } governments_iterate_end;
 
2290
 
 
2291
 
2165
2292
  /* titles */
2166
 
  government_iterate(g) {
2167
 
    struct ruler_title *title;
2168
 
    const int i = government_index(g);
2169
 
 
2170
 
    g->num_ruler_titles = 1;
2171
 
    g->ruler_titles = fc_calloc(1, sizeof(*g->ruler_titles));
2172
 
    title = &(g->ruler_titles[0]);
2173
 
 
2174
 
    title->nation = DEFAULT_TITLE;
2175
 
    sz_strlcpy(title->male.vernacular,
2176
 
               secfile_lookup_str(file, "%s.ruler_male_title", sec[i]));
2177
 
    title->male.translated = NULL;
2178
 
    sz_strlcpy(title->female.vernacular,
2179
 
               secfile_lookup_str(file, "%s.ruler_female_title", sec[i]));
2180
 
    title->female.translated = NULL;
2181
 
  } government_iterate_end;
2182
 
 
2183
 
  free(sec);
2184
 
  section_file_check_unused(file, filename);
2185
 
  section_file_free(file);
 
2293
  governments_iterate(g) {
 
2294
    const char *sec_name =
 
2295
        section_name(section_list_get(sec, government_index(g)));
 
2296
    const char *male, *female;
 
2297
 
 
2298
    if (!(male = secfile_lookup_str(file, "%s.ruler_male_title", sec_name))
 
2299
        || !(female = secfile_lookup_str(file, "%s.ruler_female_title",
 
2300
                                         sec_name))) {
 
2301
      ruleset_error(LOG_FATAL, "Lack of default ruler titles for "
 
2302
                    "government \"%s\" (nb %d): %s",
 
2303
                    government_rule_name(g), government_number(g),
 
2304
                    secfile_error());
 
2305
    } else if (NULL == government_ruler_title_new(g, NULL, male, female)) {
 
2306
      ruleset_error(LOG_FATAL, "Lack of default ruler titles for "
 
2307
                    "government \"%s\" (nb %d).",
 
2308
                    government_rule_name(g), government_number(g));
 
2309
    }
 
2310
  } governments_iterate_end;
 
2311
 
 
2312
  section_list_destroy(sec);
 
2313
  secfile_check_unused(file);
 
2314
  secfile_destroy(file);
2186
2315
}
2187
2316
 
2188
2317
/**************************************************************************
2204
2333
  lsend_packet_ruleset_control(dest, &packet);
2205
2334
}
2206
2335
 
2207
 
/**************************************************************************
2208
 
This checks if nations[pos] leader names are not already defined in any 
2209
 
previous nation, or twice in its own leader name table.
2210
 
If not return NULL, if yes return pointer to name which is repeated
2211
 
and id of a conflicting nation as second parameter.
2212
 
**************************************************************************/
2213
 
static char *check_leader_names(Nation_type_id nation,
2214
 
             Nation_type_id *conflict_nation)
 
2336
/****************************************************************************
 
2337
  This checks if nations[pos] leader names are not already defined in any
 
2338
  previous nation, or twice in its own leader name table.
 
2339
  If not return NULL, if yes return pointer to name which is repeated
 
2340
  and id of a conflicting nation as second parameter.
 
2341
****************************************************************************/
 
2342
static const char *check_leader_names(struct nation_type *pnation,
 
2343
                                      struct nation_type **ppconflict_nation)
2215
2344
{
2216
 
  int k;
2217
 
  struct nation_type *pnation = nation_by_number(nation);
2218
 
 
2219
 
  for (k = 0; k < pnation->leader_count; k++) {
2220
 
    char *leader = pnation->leaders[k].name;
2221
 
    int i;
2222
 
    Nation_type_id nation2;
2223
 
 
2224
 
    for (i = 0; i < k; i++) {
2225
 
      if (0 == strcmp(leader, pnation->leaders[i].name)) {
2226
 
        *conflict_nation = nation;
2227
 
        return leader;
2228
 
      }
2229
 
    }
2230
 
 
2231
 
    for (nation2 = 0; nation2 < nation; nation2++) {
2232
 
      struct nation_type *pnation2 = nation_by_number(nation2);
2233
 
 
2234
 
      for (i = 0; i < pnation2->leader_count; i++) {
2235
 
        if (0 == strcmp(leader, pnation2->leaders[i].name)) {
2236
 
          *conflict_nation = nation2;
2237
 
          return leader;
2238
 
        }
2239
 
      }
2240
 
    }
2241
 
  }
 
2345
  nation_leader_list_iterate(nation_leaders(pnation), pleader) {
 
2346
    const char *name = nation_leader_name(pleader);
 
2347
 
 
2348
    nation_leader_list_iterate(nation_leaders(pnation), prev_leader) {
 
2349
      if (prev_leader == pleader) {
 
2350
        break;
 
2351
      } else if (0 == fc_strcasecmp(name, nation_leader_name(prev_leader))) {
 
2352
        *ppconflict_nation = pnation;
 
2353
        return name;
 
2354
      }
 
2355
    } nation_leader_list_iterate_end;
 
2356
  } nation_leader_list_iterate_end;
 
2357
 
 
2358
  nations_iterate(prev_nation) {
 
2359
    if (prev_nation == pnation) {
 
2360
      break;
 
2361
    }
 
2362
 
 
2363
    nation_leader_list_iterate(nation_leaders(prev_nation), pleader) {
 
2364
      const char *name = nation_leader_name(pleader);
 
2365
 
 
2366
      nation_leader_list_iterate(nation_leaders(prev_nation), prev_leader) {
 
2367
        if (prev_leader == pleader) {
 
2368
          break;
 
2369
        } else if (0 == fc_strcasecmp(name,
 
2370
                                      nation_leader_name(prev_leader))) {
 
2371
          *ppconflict_nation = prev_nation;
 
2372
          return name;
 
2373
        }
 
2374
      } nation_leader_list_iterate_end;
 
2375
    } nation_leader_list_iterate_end;
 
2376
  } nations_iterate_end;
2242
2377
  return NULL;
2243
2378
}
2244
2379
 
2247
2382
**************************************************************************/
2248
2383
static void load_nation_names(struct section_file *file)
2249
2384
{
2250
 
  char **sec;
 
2385
  struct section_list *sec;
2251
2386
  int j;
2252
2387
 
2253
 
  (void) section_file_lookup(file, "datafile.description");     /* unused */
 
2388
  (void) secfile_entry_by_path(file, "datafile.description");   /* unused */
2254
2389
 
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);
 
2391
  if (NULL == sec) {
 
2392
    ruleset_error(LOG_FATAL, "No available nations in this ruleset!");
 
2393
  }
 
2394
  game.control.nation_count = section_list_size(sec);
2256
2395
  nations_alloc(game.control.nation_count);
2257
2396
 
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);
2262
2402
 
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);
2267
2405
 
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);
2271
2409
 
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
 
2423
         * distinct. */
 
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);
2278
2437
      }
2279
2438
    }
2280
2439
  } nations_iterate_end;
2281
 
  free(sec);
 
2440
  section_list_destroy(sec);
2282
2441
}
2283
2442
 
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)
2292
2452
{
2293
 
  int dim, j;
2294
 
  struct nation_city *city_names;
2295
 
  int value;
2296
 
 
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);
2300
 
 
2301
 
  /*
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.
2305
 
   */
2306
 
  city_names = fc_calloc(dim + 1, sizeof(*city_names));
2307
 
  city_names[dim].name = NULL;
2308
 
 
2309
 
  /*
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.
2317
 
   */
2318
 
  for (j = 0, value = 1; j < dim; j++, value++) {
2319
 
    char *name = strchr(cities[j], '(');
2320
 
 
2321
 
    /*
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...
2327
 
     */
2328
 
    memset(city_names[j].terrain, 0,
2329
 
           terrain_count() * sizeof(city_names[j].terrain[0]));
2330
 
    city_names[j].river = 0;
2331
 
 
2332
 
    if (name) {
2333
 
      /*
2334
 
       * 0-terminate the original string, then find the
2335
 
       * close-parenthesis so that we can make sure we stop there.
2336
 
       */
2337
 
      char *next = strchr(name + 1, ')');
2338
 
      if (!next) {
2339
 
        ruleset_error(LOG_ERROR,
2340
 
                      "\"%s\" [%s] %s: city name \"%s\" unmatched parenthesis.",
2341
 
                      secfile_filename(file),
2342
 
                      secfile_str1,
2343
 
                      secfile_str2,
2344
 
                      cities[j]);
2345
 
      } else { /* if (!next) */
2346
 
        name[0] = next[0] = '\0';
2347
 
        name++;
2348
 
 
2349
 
        /* Handle the labels one at a time. */
2350
 
        do {
2351
 
          int setting;
2352
 
 
2353
 
          next = strchr(name, ',');
2354
 
          if (next) {
2355
 
            next[0] = '\0';
2356
 
          }
2357
 
          remove_leading_trailing_spaces(name);
2358
 
        
2359
 
          /*
2360
 
           * The ! is used to mark a negative, which is recorded
2361
 
           * with a -1.  Otherwise we use a 1.
2362
 
           */
2363
 
          if (name[0] == '!') {
2364
 
            name++;
2365
 
            setting = -1;
2366
 
          } else {
2367
 
            setting = 1;
2368
 
          }
2369
 
        
2370
 
          if (mystrcasecmp(name, "river") == 0) {
2371
 
            city_names[j].river = setting;
2372
 
          } else {
2373
 
            /* "handled" tracks whether we find a match (for error handling) */
2374
 
            bool handled = FALSE;
2375
 
            int l = strlen(name);
2376
 
 
2377
 
            if (l > 0  && 's' == my_tolower(name[l-1])) {
2378
 
              /* remove frequent trailing 's' */
2379
 
              name[--l] = '\0';
2380
 
            }
2381
 
 
2382
 
            terrain_type_iterate(pterrain) {
2383
 
              const int i = terrain_index(pterrain);
2384
 
              const char *isection = &terrain_sections[i * MAX_SECTION_LABEL];
2385
 
              /*
2386
 
               * Note that the section name is unique (by definition).
2387
 
               * The sub-strings are carefully crafted for this function.
2388
 
               */
2389
 
              if (NULL != mystrcasestr(isection, name)) {
2390
 
                city_names[j].terrain[i] = setting;
2391
 
                handled = TRUE;
2392
 
                break;
2393
 
              }
2394
 
            } terrain_type_iterate_end;
2395
 
            if (!handled) {
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;"
2403
 
                            " skipping it.",
2404
 
                            secfile_filename(file),
2405
 
                            secfile_str1,
2406
 
                            secfile_str2,
2407
 
                            name);
2408
 
            }
2409
 
          }
2410
 
          name = next ? next + 1 : NULL;
2411
 
        } while (name && name[0] != '\0');
2412
 
      } /* if (!next) */
2413
 
    } /* if (name) */
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;"
2421
 
                    " shortening it.",
2422
 
                    secfile_filename(file),
2423
 
                    secfile_str1,
2424
 
                    secfile_str2,
2425
 
                    city_names[j].name);
2426
 
      city_names[j].name[MAX_LEN_NAME - 1] = '\0';
 
2453
  size_t dim, j;
 
2454
  const char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
 
2455
                                               secfile_str1, secfile_str2);
 
2456
 
 
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;
 
2466
 
 
2467
    sz_strlcpy(city_name, cities[j]);
 
2468
 
 
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, '('))) {
 
2475
      *p++ = '\0';
 
2476
 
 
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]);
 
2481
      }
 
2482
 
 
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]);
 
2489
        }
 
2490
      }
 
2491
    }
 
2492
 
 
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';
 
2502
    }
 
2503
    pncity = nation_city_new(pnation, city_name);
 
2504
 
 
2505
    if (NULL != p) {
 
2506
      /* Handle the labels one at a time. */
 
2507
      do {
 
2508
        enum nation_city_preference prefer;
 
2509
 
 
2510
        if ((next = strchr(p, ','))) {
 
2511
          *next = '\0';
 
2512
        }
 
2513
        remove_leading_trailing_spaces(p);
 
2514
 
 
2515
        /* The ! is used to mark a negative, which is recorded with
 
2516
         * NCP_DISLIKE. Otherwise we use a NCP_LIKE.
 
2517
         */
 
2518
        if (*p == '!') {
 
2519
          p++;
 
2520
          prefer = NCP_DISLIKE;
 
2521
        } else {
 
2522
          prefer = NCP_LIKE;
 
2523
        }
 
2524
 
 
2525
        if (0 == fc_strcasecmp(p, "river")) {
 
2526
          nation_city_set_river_preference(pncity, prefer);
 
2527
        } else {
 
2528
          const struct terrain *pterrain = terrain_by_rule_name(p);
 
2529
 
 
2530
          if (NULL == pterrain) {
 
2531
            /* Try with removing frequent trailing 's'. */
 
2532
            size_t l = strlen(p);
 
2533
 
 
2534
            if (0 < l && 's' == fc_tolower(p[l - 1])) {
 
2535
              p[l - 1] = '\0';
 
2536
            }
 
2537
            pterrain = terrain_by_rule_name(p);
 
2538
          }
 
2539
 
 
2540
          if (NULL != pterrain) {
 
2541
            nation_city_set_terrain_preference(pncity, pterrain, prefer);
 
2542
          } else {
 
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;"
 
2549
                         " skipping it.",
 
2550
                         secfile_name(file), secfile_str1, secfile_str2, p);
 
2551
          }
 
2552
        }
 
2553
 
 
2554
        p = next ? next + 1 : NULL;
 
2555
      } while (NULL != p && '\0' != *p);
2427
2556
    }
2428
2557
  }
2429
 
  if (cities) {
 
2558
 
 
2559
  if (NULL != cities) {
2430
2560
    free(cities);
2431
2561
  }
2432
 
  return city_names;
2433
2562
}
2434
2563
 
2435
2564
/**************************************************************************
2437
2566
**************************************************************************/
2438
2567
static void load_ruleset_nations(struct section_file *file)
2439
2568
{
2440
 
  char *bad_leader, *govern;
2441
2569
  struct government *gov;
2442
 
  int dim, i, i2, j, k, nval, numgroups;
 
2570
  int j;
 
2571
  size_t dim;
2443
2572
  char temp_name[MAX_LEN_NAME];
2444
 
  char **leaders, **sec, **civilwar_nations, **groups, **conflicts;
2445
 
  char* name;
 
2573
  const char **vec;
 
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);
2449
 
 
2450
 
  (void) check_ruleset_capabilities(file, "+1.9", filename);
2451
 
  
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]);
2458
 
  }
2459
 
  free(groups);
2460
 
 
2461
 
  sec = secfile_get_secnames_prefix(file, NATION_SECTION_PREFIX, &nval);
2462
 
 
2463
 
  nations_iterate(pl) {
2464
 
    const int i = nation_index(pl);
 
2577
  const char *filename = secfile_name(file);
 
2578
  struct section_list *sec;
 
2579
 
 
2580
  (void) check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
 
2581
 
 
2582
  sec = secfile_sections_by_name_prefix(file, NATION_GROUP_SECTION_PREFIX);
 
2583
  section_list_iterate(sec, psection) {
 
2584
    struct nation_group *pgroup;
 
2585
 
 
2586
    name = secfile_lookup_str(file, "%s.name", section_name(psection));
 
2587
    if (NULL == name) {
 
2588
      ruleset_error(LOG_FATAL, "Error: %s", secfile_error());
 
2589
    }
 
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());
 
2593
    }
 
2594
    nation_group_set_match(pgroup, j);
 
2595
  } section_list_iterate_end;
 
2596
  section_list_destroy(sec);
 
2597
 
 
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";
2466
 
    char *barb_type;
2467
 
 
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)));
2471
 
 
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),
2477
 
                groups[j]);
2478
 
      }
2479
 
    }
2480
 
    pl->groups[dim] = NULL; /* extra at end of list */
2481
 
    free(groups);
2482
 
    
2483
 
    conflicts = 
2484
 
      secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec[i]);
2485
 
    pl->conflicts_with = fc_calloc(dim + 1, sizeof(*(pl->conflicts_with)));
2486
 
 
2487
 
    for (j = 0, k = 0; k < dim; j++, k++) {
2488
 
      pl->conflicts_with[j] = find_nation_by_rule_name(conflicts[k]);
2489
 
 
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
2494
 
         * exist. */
2495
 
        j--;
2496
 
        freelog(LOG_VERBOSE,
2497
 
                "Nation %s: conflicts_with nation \"%s\" is unknown.",
2498
 
                nation_rule_name(pl),
2499
 
                conflicts[k]);
2500
 
      }
2501
 
    }
2502
 
    pl->conflicts_with[j] = NO_NATION_SELECTED; /* extra at end of list */
2503
 
    free(conflicts);
2504
 
 
2505
 
    /* nation leaders */
2506
 
 
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),
2511
 
              MAX_NUM_LEADERS,
2512
 
              dim);
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),
2518
 
                    dim);
2519
 
    }
2520
 
    pl->leader_count = dim;
2521
 
    pl->leaders = fc_calloc(dim /*exact*/, sizeof(*(pl->leaders)));
2522
 
 
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';
2527
 
      }
2528
 
    }
2529
 
    free(leaders);
2530
 
 
2531
 
    /* check if leader name is not already defined */
2532
 
    if ((bad_leader = check_leader_names(i, &i2))) {
2533
 
        if (i == i2) {
2534
 
          ruleset_error(LOG_FATAL,
2535
 
                        "Nation %s: leader \"%s\" defined more than once.",
2536
 
                        nation_rule_name(pl),
2537
 
                        bad_leader);
2538
 
        } else {
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)),
2543
 
                        bad_leader);
2544
 
        }
2545
 
    }
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),
2553
 
                    dim,
2554
 
                    pl->leader_count);
2555
 
    }
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;
2561
 
      } else {
2562
 
        freelog(LOG_ERROR,
2563
 
                "Nation %s, leader %s: sex must be either Male or Female; "
2564
 
                "assuming Male",
2565
 
                nation_rule_name(pl),
2566
 
                pl->leaders[j].name);
2567
 
        pl->leaders[j].is_male = TRUE;
2568
 
      }
2569
 
    }
2570
 
    free(leaders);
2571
 
    
2572
 
    pl->is_available = secfile_lookup_bool_default(file, TRUE,
2573
 
                                                   "%s.is_available", sec[i]);
2574
 
 
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));
 
2605
 
 
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]);
 
2610
 
 
2611
      if (NULL != pgroup) {
 
2612
        nation_group_list_append(pnation->groups, pgroup);
 
2613
      } else {
 
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
 
2617
         * exist. */
 
2618
        log_verbose("Nation %s: Unknown group \"%s\".",
 
2619
                    nation_rule_name(pnation), vec[j]);
 
2620
      }
 
2621
    }
 
2622
    if (NULL != vec) {
 
2623
      free(vec);
 
2624
    }
 
2625
 
 
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]);
 
2630
 
 
2631
      if (NULL != pconflict) {
 
2632
        nation_list_append(pnation->server.conflicts_with, pconflict);
 
2633
      } else {
 
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
 
2637
         * exist. */
 
2638
        log_verbose("Nation %s: conflicts_with nation \"%s\" is unknown.",
 
2639
                    nation_rule_name(pnation), vec[j]);
 
2640
      }
 
2641
    }
 
2642
    if (NULL != vec) {
 
2643
      free(vec);
 
2644
    }
 
2645
 
 
2646
    /* Nation leaders. */
 
2647
    for (j = 0; j < MAX_NUM_LEADERS; j++) {
 
2648
      const char *sex;
 
2649
      bool is_male = FALSE;
 
2650
 
 
2651
      name = secfile_lookup_str(file, "%s.leaders%d.name", sec_name, j);
 
2652
      if (NULL == name) {
 
2653
        /* No more to read. */
 
2654
        break;
 
2655
      }
 
2656
 
 
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);
 
2664
        name = temp_name;
 
2665
      }
 
2666
 
 
2667
      sex = secfile_lookup_str(file, "%s.leaders%d.sex", sec_name, j);
 
2668
      if (NULL == sex) {
 
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)) {
 
2672
        is_male = TRUE;
 
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);
 
2677
      }
 
2678
      (void) nation_leader_new(pnation, name, is_male);
 
2679
    }
 
2680
 
 
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",
 
2685
                                          sec_name, j)) {
 
2686
        j++;
 
2687
      }
 
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));
 
2694
    }
 
2695
 
 
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);
 
2702
      } else {
 
2703
        ruleset_error(LOG_FATAL,
 
2704
                      "Nations %s and %s share the same leader \"%s\".",
 
2705
                      nation_rule_name(pnation), nation_rule_name(pconflict),
 
2706
                      bad_leader);
 
2707
      }
 
2708
    }
 
2709
 
 
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);
 
2714
 
 
2715
    if (pnation->is_playable) {
2578
2716
      server.playable_nations++;
2579
2717
    }
2580
2718
 
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));
2593
2731
      }
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));
2603
2741
      }
2604
 
      pl->barb_type = SEA_BARBARIAN;
 
2742
      pnation->barb_type = SEA_BARBARIAN;
2605
2743
      barb_sea_count++;
2606
2744
    } else {
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),
2611
 
                    barb_type);
 
2748
                    nation_rule_name(pnation), barb_type);
2612
2749
    }
2613
2750
 
2614
2751
    /* Flags */
2615
 
 
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));
2620
2757
 
2621
2758
    /* Ruler titles */
2622
 
 
2623
 
    j = -1;
2624
 
    while ((govern = secfile_lookup_str_default(file, NULL,
2625
 
                                           "%s.ruler_titles%d.government",
2626
 
                                           sec[i], ++j))) {
2627
 
      char *male_name;
2628
 
      char *female_name;
2629
 
      
2630
 
      male_name = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
2631
 
                                     sec[i], j);
2632
 
      female_name = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
2633
 
                                       sec[i], j);
2634
 
 
2635
 
      gov = find_government_by_rule_name(govern);
2636
 
      if (gov) {
2637
 
        struct ruler_title *title;
2638
 
 
2639
 
        gov->num_ruler_titles++;
2640
 
        gov->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]);
2644
 
 
2645
 
        title->nation = pl;
2646
 
 
2647
 
        name_strlcpy(title->male.vernacular, male_name);
2648
 
        title->male.translated = NULL;
2649
 
 
2650
 
        name_strlcpy(title->female.vernacular, female_name);
2651
 
        title->female.translated = NULL;
 
2759
    for (j = 0;; j++) {
 
2760
      const char *male, *female;
 
2761
 
 
2762
      name = secfile_lookup_str_default(file, NULL,
 
2763
                                        "%s.ruler_titles%d.government",
 
2764
                                        sec_name, j);
 
2765
      if (NULL == name) {
 
2766
        /* End of the list of ruler titles. */
 
2767
        break;
 
2768
      }
 
2769
 
 
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",
 
2773
                                sec_name, j);
 
2774
      female = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
 
2775
                                  sec_name, j);
 
2776
      gov = government_by_rule_name(name);
 
2777
 
 
2778
      if (NULL == gov) {
 
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);
2652
2785
      } else {
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),
2658
 
                govern);
 
2786
          ruleset_error(LOG_ERROR, "%s", secfile_error());
2659
2787
      }
2660
2788
    }
2661
2789
 
2662
2790
    /* City styles */
2663
 
 
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) {
2668
 
      freelog(LOG_ERROR,
2669
 
              "Nation %s: city style \"%s\" is unknown, using default.", 
2670
 
              nation_rule_name(pl),
2671
 
              temp_name);
2672
 
      pl->city_style = 0;
 
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;
2673
2797
    }
2674
2798
 
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. */
2682
2805
      }
2683
 
      freelog(LOG_ERROR,
2684
 
              "Nation %s: city style \"%s\" is not available from beginning; "
2685
 
              "using default.",
2686
 
              nation_rule_name(pl),
2687
 
              temp_name);
2688
 
      pl->city_style = 0;
 
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;
2689
2810
    }
2690
2811
 
2691
2812
    /* Civilwar nations */
2692
 
 
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)));
2696
 
 
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]);
2699
2817
 
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. */
2703
 
 
2704
 
      if (pl->civilwar_nations[j] == NO_NATION_SELECTED) {
2705
 
        j--;
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
2709
 
         * exist. */
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);
 
2824
      } else {
 
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
 
2828
         * exist. */
 
2829
        log_verbose("Nation %s: civil war nation \"%s\" is unknown.",
 
2830
                    nation_rule_name(pnation), vec[j]);
2714
2831
      }
2715
2832
    }
2716
 
    pl->civilwar_nations[j] = NO_NATION_SELECTED; /* end of list */
2717
 
    free(civilwar_nations);
 
2833
    if (NULL != vec) {
 
2834
      free(vec);
 
2835
    }
2718
2836
 
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,
2722
 
                         filename);
2723
 
    lookup_unit_list(file, sec[i], "init_units", LOG_ERROR, pl->init_units,
2724
 
                     filename);
2725
 
    mystrlcat(tmp, sec[i], 200);
2726
 
    mystrlcat(tmp, ".init_government", 200);
2727
 
    pl->init_government = lookup_government(file, tmp, filename);
2728
 
 
2729
 
    /* read "normal" city names */
2730
 
 
2731
 
    pl->city_names = load_city_name_list(file, sec[i], "cities");
2732
 
 
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);
 
2847
 
 
2848
    /* Read default city names. */
 
2849
    load_city_name_list(file, pnation, sec_name, "cities");
 
2850
 
 
2851
    pnation->legend = fc_strdup(secfile_lookup_str(file, "%s.legend",
 
2852
                                                   sec_name));
 
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),
 
2857
                    pnation->legend);
 
2858
      pnation->legend[MAX_LEN_MSG - 1] = '\0';
2736
2859
    }
2737
2860
 
2738
 
    pl->player = NULL;
2739
 
  } nations_iterate_end;
2740
 
 
2741
 
  /* Calculate parent nations.  O(n^2) algorithm. */
2742
 
  nations_iterate(pl) {
2743
 
    struct nation_type *parents[nation_count()];
2744
 
    int count = 0;
2745
 
 
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;
2750
 
          count++;
2751
 
        }
2752
 
      }
2753
 
    } nations_iterate_end;
2754
 
 
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;
2760
 
 
2761
 
  free(sec);
2762
 
  section_file_check_unused(file, filename);
2763
 
  section_file_free(file);
 
2861
    pnation->player = NULL;
 
2862
  } nations_iterate_end;
 
2863
 
 
2864
  section_list_destroy(sec);
 
2865
  secfile_check_unused(file);
 
2866
  secfile_destroy(file);
2764
2867
 
2765
2868
  if (barb_land_count == 0) {
2766
2869
    ruleset_error(LOG_FATAL,
2777
2880
**************************************************************************/
2778
2881
static void load_citystyle_names(struct section_file *file)
2779
2882
{
2780
 
  char **styles;
2781
 
  int nval, i;
 
2883
  struct section_list *styles;
 
2884
  int i = 0;
2782
2885
 
2783
 
  (void) section_file_lookup(file, "datafile.description");     /* unused */
 
2886
  (void) secfile_entry_by_path(file, "datafile.description");   /* unused */
2784
2887
 
2785
2888
  /* The sections: */
2786
 
  styles = secfile_get_secnames_prefix(file, CITYSTYLE_SECTION_PREFIX, &nval);
2787
 
  city_styles_alloc(nval);
2788
 
 
2789
 
  /* Get names, so can lookup for replacements: */
2790
 
  for (i = 0; i < game.control.styles_count; i++) {
2791
 
    char *style_name = secfile_lookup_str(file, "%s.name", styles[i]);
2792
 
    name_strlcpy(city_styles[i].name.vernacular, style_name);
2793
 
    city_styles[i].name.translated = NULL;
 
2889
  styles = secfile_sections_by_name_prefix(file, CITYSTYLE_SECTION_PREFIX);
 
2890
  if (NULL != styles) {
 
2891
    city_styles_alloc(section_list_size(styles));
 
2892
    section_list_iterate(styles, style) {
 
2893
      ruleset_load_names(&city_styles[i].name, file, section_name(style));
 
2894
      i++;
 
2895
    } section_list_iterate_end;
 
2896
    section_list_destroy(styles);
 
2897
  } else {
 
2898
    city_styles_alloc(0);
2794
2899
  }
2795
 
  free(styles);
2796
2900
}
2797
2901
 
2798
2902
/**************************************************************************
2800
2904
**************************************************************************/
2801
2905
static void load_ruleset_cities(struct section_file *file)
2802
2906
{
2803
 
  char **styles, **sec, *replacement;
2804
 
  int i, nval;
2805
 
  const char *filename = secfile_filename(file);
2806
 
  char *item;
 
2907
  const char *replacement;
 
2908
  int i;
 
2909
  const char *filename = secfile_name(file);
 
2910
  const char *item;
 
2911
  struct section_list *sec;
2807
2912
 
2808
 
  (void) check_ruleset_capabilities(file, "+1.9", filename);
 
2913
  (void) check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
2809
2914
 
2810
2915
  /* Specialist options */
2811
 
  sec = secfile_get_secnames_prefix(file, SPECIALIST_SECTION_PREFIX, &nval);
2812
 
  if (nval >= SP_MAX) {
 
2916
  sec = secfile_sections_by_name_prefix(file, SPECIALIST_SECTION_PREFIX);
 
2917
  if (section_list_size(sec) >= SP_MAX) {
2813
2918
    ruleset_error(LOG_FATAL, "\"%s\": Too many specialists (%d, max %d).",
2814
 
            filename, nval, SP_MAX);
 
2919
                  filename, section_list_size(sec), SP_MAX);
2815
2920
  }
2816
 
  game.control.num_specialist_types = nval;
 
2921
  game.control.num_specialist_types = section_list_size(sec);
2817
2922
 
2818
 
  for (i = 0; i < nval; i++) {
 
2923
  i = 0;
 
2924
  section_list_iterate(sec, psection) {
2819
2925
    struct specialist *s = specialist_by_number(i);
2820
2926
    struct requirement_vector *reqs;
2821
 
 
2822
 
    item = secfile_lookup_str(file, "%s.name", sec[i]);
2823
 
    sz_strlcpy(s->name.vernacular, item);
2824
 
    s->name.translated = NULL;
2825
 
 
2826
 
    item = secfile_lookup_str_default(file, s->name.vernacular,
2827
 
                                      "%s.short_name",
2828
 
                                      sec[i]);
2829
 
    sz_strlcpy(s->abbreviation.vernacular, item);
2830
 
    s->abbreviation.translated = NULL;
2831
 
 
2832
 
    reqs = lookup_req_list(file, sec[i], "reqs", specialist_rule_name(s));
 
2927
    const char *sec_name = section_name(psection);
 
2928
 
 
2929
    ruleset_load_names(&s->name, file, sec_name);
 
2930
 
 
2931
    item = secfile_lookup_str_default(file, untranslated_name(&s->name),
 
2932
                                      "%s.short_name", sec_name);
 
2933
    name_set(&s->abbreviation, item);
 
2934
 
 
2935
    reqs = lookup_req_list(file, sec_name, "reqs", specialist_rule_name(s));
2833
2936
    requirement_vector_copy(&s->reqs, reqs);
2834
2937
 
 
2938
    s->helptext = lookup_strvec(file, sec_name, "helptext");
 
2939
 
2835
2940
    if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
2836
2941
      DEFAULT_SPECIALIST = i;
2837
2942
    }
2838
 
  }
 
2943
    i++;
 
2944
  } section_list_iterate_end;
2839
2945
  if (DEFAULT_SPECIALIST == -1) {
2840
2946
    ruleset_error(LOG_FATAL,
2841
2947
                  "\"%s\": must give a min_size of 0 for at least one "
2842
2948
                  "specialist type.", filename);
2843
2949
  }
2844
 
  free(sec);
 
2950
  section_list_destroy(sec);
2845
2951
 
2846
2952
  /* City Parameters */
2847
2953
 
2870
2976
  }
2871
2977
 
2872
2978
  /* civ1 & 2 didn't reveal tiles */
2873
 
  game.info.vision_reveal_tiles =
 
2979
  game.server.vision_reveal_tiles =
2874
2980
    secfile_lookup_bool_default(file, FALSE, "parameters.vision_reveal_tiles");
2875
2981
 
2876
2982
  /* City Styles ... */
2877
2983
 
2878
 
  styles = secfile_get_secnames_prefix(file, CITYSTYLE_SECTION_PREFIX, &nval);
 
2984
  sec = secfile_sections_by_name_prefix(file, CITYSTYLE_SECTION_PREFIX);
2879
2985
 
2880
2986
  /* Get rest: */
2881
2987
  for (i = 0; i < game.control.styles_count; i++) {
2882
2988
    struct requirement_vector *reqs;
 
2989
    const char *sec_name = section_name(section_list_get(sec, i));
2883
2990
 
2884
2991
    sz_strlcpy(city_styles[i].graphic, 
2885
 
               secfile_lookup_str(file, "%s.graphic", styles[i]));
 
2992
               secfile_lookup_str(file, "%s.graphic", sec_name));
2886
2993
    sz_strlcpy(city_styles[i].graphic_alt, 
2887
 
               secfile_lookup_str(file, "%s.graphic_alt", styles[i]));
 
2994
               secfile_lookup_str(file, "%s.graphic_alt", sec_name));
2888
2995
    sz_strlcpy(city_styles[i].oceanic_graphic, 
2889
2996
               secfile_lookup_str_default(file, "",
2890
 
                                          "%s.oceanic_graphic", styles[i]));
 
2997
                                          "%s.oceanic_graphic", sec_name));
2891
2998
    sz_strlcpy(city_styles[i].oceanic_graphic_alt, 
2892
2999
               secfile_lookup_str_default(file, "",
2893
 
                                          "%s.oceanic_graphic_alt", styles[i]));
 
3000
                                          "%s.oceanic_graphic_alt",
 
3001
                                          sec_name));
2894
3002
    sz_strlcpy(city_styles[i].citizens_graphic,
2895
3003
               secfile_lookup_str_default(file, "-", 
2896
 
                        "%s.citizens_graphic", styles[i]));
 
3004
                        "%s.citizens_graphic", sec_name));
2897
3005
    sz_strlcpy(city_styles[i].citizens_graphic_alt, 
2898
3006
               secfile_lookup_str_default(file, "generic", 
2899
 
                        "%s.citizens_graphic_alt", styles[i]));
 
3007
                        "%s.citizens_graphic_alt", sec_name));
2900
3008
 
2901
 
    reqs = lookup_req_list(file, styles[i], "reqs", city_style_rule_name(i));
 
3009
    reqs = lookup_req_list(file, sec_name, "reqs", city_style_rule_name(i));
2902
3010
    requirement_vector_copy(&city_styles[i].reqs, reqs);
2903
3011
 
2904
 
    replacement = secfile_lookup_str(file, "%s.replaced_by", styles[i]);
2905
 
    if( strcmp(replacement, "-") == 0) {
 
3012
    replacement = secfile_lookup_str(file, "%s.replaced_by", sec_name);
 
3013
    if(0 == strcmp(replacement, "-")) {
2906
3014
      city_styles[i].replaced_by = -1;
2907
3015
    } else {
2908
 
      city_styles[i].replaced_by = find_city_style_by_rule_name(replacement);
 
3016
      city_styles[i].replaced_by = city_style_by_rule_name(replacement);
2909
3017
      if (city_styles[i].replaced_by < 0) {
2910
 
        freelog(LOG_ERROR, "\"%s\": style \"%s\" replacement \"%s\" not found",
2911
 
                filename,
2912
 
                city_style_rule_name(i),
2913
 
                replacement);
 
3018
        log_error("\"%s\": style \"%s\" replacement \"%s\" not found",
 
3019
                  filename, city_style_rule_name(i), replacement);
2914
3020
      }
2915
3021
    }
2916
3022
  }
2917
 
  free(styles);
 
3023
  section_list_destroy(sec);
2918
3024
 
2919
 
  section_file_check_unused(file, filename);
2920
 
  section_file_free(file);
 
3025
  secfile_check_unused(file);
 
3026
  secfile_destroy(file);
2921
3027
}
2922
3028
 
2923
3029
/**************************************************************************
2925
3031
**************************************************************************/
2926
3032
static void load_ruleset_effects(struct section_file *file)
2927
3033
{
2928
 
  char **sec, *type;
2929
 
  int i, nval;
 
3034
  struct section_list *sec;
 
3035
  const char *type;
2930
3036
  const char *filename;
2931
3037
 
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 */
2935
3041
 
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;
2940
3046
    int value;
2941
3047
    struct effect *peffect;
 
3048
    const char *sec_name = section_name(psection);
2942
3049
 
2943
 
    type = secfile_lookup_str(file, "%s.name", sec[i]);
 
3050
    type = secfile_lookup_str(file, "%s.name", sec_name);
2944
3051
 
2945
3052
    if ((eff = effect_type_from_str(type)) == EFT_LAST) {
2946
 
      freelog(LOG_ERROR,
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);
2949
3055
      continue;
2950
3056
    }
2951
3057
 
2952
 
    value = secfile_lookup_int_default(file, 1, "%s.value", sec[i]);
 
3058
    value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
2953
3059
 
2954
3060
    peffect = effect_new(eff, value);
2955
3061
 
2956
 
    requirement_vector_iterate(lookup_req_list(file, sec[i], "reqs", type),
 
3062
    requirement_vector_iterate(lookup_req_list(file, sec_name, "reqs", type),
2957
3063
                               req) {
2958
3064
      struct requirement *preq = fc_malloc(sizeof(*preq));
2959
3065
 
2960
3066
      *preq = *req;
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,
 
3070
                                               "nreqs", type),
2964
3071
                               req) {
2965
3072
      struct requirement *preq = fc_malloc(sizeof(*preq));
2966
3073
 
2967
3074
      *preq = *req;
2968
3075
      effect_req_append(peffect, TRUE, preq);
2969
3076
    } requirement_vector_iterate_end;
2970
 
  }
2971
 
  free(sec);
2972
 
 
2973
 
  section_file_check_unused(file, filename);
2974
 
  section_file_free(file);
 
3077
  } section_list_iterate_end;
 
3078
  section_list_destroy(sec);
 
3079
 
 
3080
  secfile_check_unused(file);
 
3081
  secfile_destroy(file);
 
3082
}
 
3083
 
 
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, ...)
 
3094
{
 
3095
  char fullpath[256];
 
3096
  int ival;
 
3097
  va_list args;
 
3098
 
 
3099
  va_start(args, path);
 
3100
  fc_vsnprintf(fullpath, sizeof(fullpath), path, args);
 
3101
  va_end(args);
 
3102
 
 
3103
  if (!secfile_lookup_int(file, &ival, "%s", fullpath)) {
 
3104
    ival = def;
 
3105
  }
 
3106
 
 
3107
  if (ival < min) {
 
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);
 
3111
    ival = min;
 
3112
  }
 
3113
 
 
3114
  if (ival > max) {
 
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);
 
3118
    ival = max;
 
3119
  }
 
3120
 
 
3121
  return ival;
2975
3122
}
2976
3123
 
2977
3124
/**************************************************************************
2979
3126
**************************************************************************/
2980
3127
static void load_ruleset_game(void)
2981
3128
{
2982
 
  struct section_file file;
2983
 
  char *sval, **svec;
 
3129
  struct section_file *file;
 
3130
  const char *sval, **svec;
2984
3131
  const char *filename;
2985
3132
  int *food_ini;
2986
3133
  int i;
2987
 
  char *text;
 
3134
  size_t teams;
 
3135
  const char *text;
2988
3136
 
2989
 
  openload_ruleset_file(&file, "game");
2990
 
  filename = secfile_filename(&file);
 
3137
  file = openload_ruleset_file("game");
 
3138
  filename = secfile_name(file);
2991
3139
 
2992
3140
  /* section: datafile */
2993
 
  (void) check_ruleset_capabilities(&file, "+1.11.1", filename);
2994
 
  (void) section_file_lookup(&file, "datafile.description");    /* unused */
 
3141
  (void) check_ruleset_capabilities(file, RULESET_CAPABILITIES, filename);
 
3142
  (void) secfile_entry_by_path(file, "datafile.description");   /* unused */
2995
3143
 
2996
3144
  /* section: tileset */
2997
 
  text = secfile_lookup_str_default(&file, "", "tileset.prefered");
 
3145
  text = secfile_lookup_str_default(file, "", "tileset.prefered");
2998
3146
  if (text[0] != '\0') {
2999
3147
    /* There was tileset suggestion */
3000
3148
    sz_strlcpy(game.control.prefered_tileset, text);
3004
3152
  }
3005
3153
 
3006
3154
  /* section: about */
3007
 
  text = secfile_lookup_str(&file, "about.name");
 
3155
  text = secfile_lookup_str(file, "about.name");
3008
3156
  /* Ruleset/modpack name found */
3009
3157
  sz_strlcpy(game.control.name, text);
3010
3158
 
3011
 
  text = secfile_lookup_str_default(&file, "", "about.description");
 
3159
  text = secfile_lookup_str_default(file, "", "about.description");
3012
3160
  if (text[0] != '\0') {
3013
3161
    /* Ruleset/modpack description found */
3014
3162
    sz_strlcpy(game.control.description, text);
3018
3166
  }
3019
3167
 
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);
3025
3173
 
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,
3033
 
                                         RS_MIN_HAPPY_COST,
3034
 
                                         RS_MAX_HAPPY_COST,
3035
 
                                         "civstyle.happy_cost");
 
3179
    = secfile_lookup_int_def_min_max(file,
 
3180
                                                                         RS_DEFAULT_HAPPY_COST,
 
3181
                                     RS_MIN_HAPPY_COST,
 
3182
                                     RS_MAX_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");
3081
3229
 
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");
 
3233
 
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;
3093
3243
  } else {
3101
3251
        } else {
3102
3252
          food_ini[i] = food_ini[i - 1];
3103
3253
        }
3104
 
        freelog(LOG_ERROR, "Bad value for granary_food_ini[%i]. Using %i.",
3105
 
                i, food_ini[i]);
 
3254
        log_error("Bad value for granary_food_ini[%i]. Using %i.",
 
3255
                  i, food_ini[i]);
3106
3256
      }
3107
3257
      game.info.granary_food_ini[i] = food_ini[i];
3108
3258
    }
3110
3260
  free(food_ini);
3111
3261
 
3112
3262
  game.info.granary_food_inc
3113
 
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3263
    = secfile_lookup_int_default_min_max(file,
3114
3264
                                         RS_DEFAULT_GRANARY_FOOD_INC,
3115
3265
                                         RS_MIN_GRANARY_FOOD_INC,
3116
3266
                                         RS_MAX_GRANARY_FOOD_INC,
3118
3268
 
3119
3269
  output_type_iterate(o) {
3120
3270
    game.info.min_city_center_output[o]
3121
 
      = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3271
      = secfile_lookup_int_default_min_max(file,
3122
3272
                                           RS_DEFAULT_CITY_CENTER_OUTPUT,
3123
3273
                                           RS_MIN_CITY_CENTER_OUTPUT,
3124
3274
                                           RS_MAX_CITY_CENTER_OUTPUT,
3126
3276
                                           get_output_identifier(o));
3127
3277
  } output_type_iterate_end;
3128
3278
 
3129
 
  sval = secfile_lookup_str(&file, "civstyle.nuke_contamination" );
3130
 
  if (mystrcasecmp(sval, "Pollution") == 0) {
3131
 
    game.info.nuke_contamination = CONTAMINATION_POLLUTION;
3132
 
  } else if (mystrcasecmp(sval, "Fallout") == 0) {
3133
 
    game.info.nuke_contamination = CONTAMINATION_FALLOUT;
 
3279
  sval = secfile_lookup_str(file, "civstyle.nuke_contamination" );
 
3280
  if (fc_strcasecmp(sval, "Pollution") == 0) {
 
3281
    game.server.nuke_contamination = CONTAMINATION_POLLUTION;
 
3282
  } else if (fc_strcasecmp(sval, "Fallout") == 0) {
 
3283
    game.server.nuke_contamination = CONTAMINATION_FALLOUT;
3134
3284
  } else {
3135
 
    freelog(LOG_ERROR, "Bad value %s for nuke_contamination. Using "
3136
 
            "\"Pollution\".", sval);
3137
 
    game.info.nuke_contamination = CONTAMINATION_POLLUTION;
 
3285
    log_error("Bad value %s for nuke_contamination. Using "
 
3286
              "\"Pollution\".", sval);
 
3287
    game.server.nuke_contamination = CONTAMINATION_POLLUTION;
3138
3288
  }
3139
3289
 
3140
3290
  /* This only takes effect if citymindist is set to 0. */
3141
3291
  game.info.min_dist_bw_cities
3142
 
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3292
    = secfile_lookup_int_default_min_max(file,
3143
3293
                                         RS_DEFAULT_CITIES_MIN_DIST,
3144
3294
                                         RS_MIN_CITIES_MIN_DIST,
3145
3295
                                         RS_MAX_CITIES_MIN_DIST,
3146
3296
                                         "civstyle.min_dist_bw_cities");
3147
 
  game.info.init_vis_radius_sq
3148
 
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3297
  game.server.init_vis_radius_sq
 
3298
    = secfile_lookup_int_default_min_max(file,
3149
3299
                                         RS_DEFAULT_VIS_RADIUS_SQ,
3150
3300
                                         RS_MIN_VIS_RADIUS_SQ,
3151
3301
                                         RS_MAX_VIS_RADIUS_SQ,
3152
3302
                                         "civstyle.init_vis_radius_sq");
3153
3303
 
 
3304
  game.info.init_city_radius_sq
 
3305
    = secfile_lookup_int_default_min_max(file,
 
3306
                                         RS_DEFAULT_CITY_RADIUS_SQ,
 
3307
                                         RS_MIN_CITY_RADIUS_SQ,
 
3308
                                         RS_MAX_CITY_RADIUS_SQ,
 
3309
                                         "civstyle.init_city_radius_sq");
 
3310
 
3154
3311
  game.info.gold_upkeep_style
3155
 
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3312
    = secfile_lookup_int_default_min_max(file,
3156
3313
                                         RS_DEFAULT_GOLD_UPKEEP_STYLE,
3157
3314
                                         RS_MIN_GOLD_UPKEEP_STYLE,
3158
3315
                                         RS_MAX_GOLD_UPKEEP_STYLE,
3160
3317
 
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) {
3176
 
    freelog(LOG_ERROR,
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;
3180
3336
  }
3181
3337
 
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");
3210
3366
 
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,
3236
3392
 
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");
3241
3397
 
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");
3249
3405
 
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");
3263
3419
 
 
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");
 
3433
 
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")));
3279
3449
 
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();
3285
3454
  }
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]);
3288
3457
  }
3289
3458
  free(svec);
3290
3459
 
3291
 
  section_file_check_unused(&file, filename);
3292
 
  section_file_free(&file);
 
3460
  settings_ruleset(file, "settings");
 
3461
 
 
3462
  secfile_check_unused(file);
 
3463
  secfile_destroy(file);
3293
3464
}
3294
3465
 
3295
3466
/**************************************************************************
3302
3473
 
3303
3474
  unit_class_iterate(c) {
3304
3475
    packet.id = uclass_number(c);
3305
 
    sz_strlcpy(packet.name, c->name.vernacular);
 
3476
    sz_strlcpy(packet.name, untranslated_name(&c->name));
 
3477
    sz_strlcpy(packet.rule_name, rule_name(&c->name));
3306
3478
    packet.move_type = c->move_type;
3307
3479
    packet.min_speed = c->min_speed;
3308
3480
    packet.hp_loss_pct = c->hp_loss_pct;
3324
3496
 
3325
3497
  unit_type_iterate(u) {
3326
3498
    packet.id = utype_number(u);
3327
 
    sz_strlcpy(packet.name, u->name.vernacular);
 
3499
    sz_strlcpy(packet.name, untranslated_name(&u->name));
 
3500
    sz_strlcpy(packet.rule_name, rule_name(&u->name));
3328
3501
    sz_strlcpy(packet.sound_move, u->sound_move);
3329
3502
    sz_strlcpy(packet.sound_move_alt, u->sound_move_alt);
3330
3503
    sz_strlcpy(packet.sound_fight, u->sound_fight);
3349
3522
    packet.firepower = u->firepower;
3350
3523
    packet.obsoleted_by = u->obsoleted_by
3351
3524
                          ? utype_number(u->obsoleted_by) : -1;
 
3525
    packet.converted_to = u->converted_to
 
3526
                          ? utype_number(u->converted_to) : -1;
3352
3527
    packet.fuel = u->fuel;
3353
3528
    packet.flags = u->flags;
3354
3529
    packet.roles = u->roles;
3364
3539
    packet.cargo = u->cargo;
3365
3540
    packet.targets = u->targets;
3366
3541
    for (i = 0; i < MAX_VET_LEVELS; i++) {
3367
 
      sz_strlcpy(packet.veteran_name[i], u->veteran[i].name);
 
3542
      sz_strlcpy(packet.veteran_name[i], untranslated_name(&u->veteran[i].name));
3368
3543
      packet.power_fact[i] = u->veteran[i].power_fact;
3369
3544
      packet.move_bonus[i] = u->veteran[i].move_bonus;
3370
3545
    }
3371
 
    if (u->helptext) {
3372
 
      sz_strlcpy(packet.helptext, u->helptext);
3373
 
    } else {
3374
 
      packet.helptext[0] = '\0';
3375
 
    }
 
3546
    PACKET_STRVEC_COMPUTE(packet.helptext, u->helptext);
3376
3547
 
3377
3548
    lsend_packet_ruleset_unit(dest, &packet);
3378
3549
  } unit_type_iterate_end;
3391
3562
    int j;
3392
3563
 
3393
3564
    packet.id = spec_id;
3394
 
    sz_strlcpy(packet.name, s->name.vernacular);
3395
 
    sz_strlcpy(packet.short_name, s->abbreviation.vernacular);
 
3565
    sz_strlcpy(packet.plural_name, untranslated_name(&s->name));
 
3566
    sz_strlcpy(packet.rule_name, rule_name(&s->name));
 
3567
    sz_strlcpy(packet.short_name, untranslated_name(&s->abbreviation));
3396
3568
    j = 0;
3397
3569
    requirement_vector_iterate(&s->reqs, preq) {
3398
3570
      packet.reqs[j++] = *preq;
3399
3571
    } requirement_vector_iterate_end;
3400
3572
    packet.reqs_count = j;
3401
3573
 
 
3574
    PACKET_STRVEC_COMPUTE(packet.helptext, s->helptext);
 
3575
 
3402
3576
    lsend_packet_ruleset_specialist(dest, &packet);
3403
3577
  } specialist_type_iterate_end;
3404
3578
}
3413
3587
 
3414
3588
  advance_iterate(A_NONE, a) {
3415
3589
    packet.id = advance_number(a);
3416
 
    sz_strlcpy(packet.name, a->name.vernacular);
 
3590
    sz_strlcpy(packet.name, untranslated_name(&a->name));
 
3591
    sz_strlcpy(packet.rule_name, rule_name(&a->name));
3417
3592
    sz_strlcpy(packet.graphic_str, a->graphic_str);
3418
3593
    sz_strlcpy(packet.graphic_alt, a->graphic_alt);
3419
3594
 
3427
3602
    packet.flags = a->flags;
3428
3603
    packet.preset_cost = a->preset_cost;
3429
3604
    packet.num_reqs = a->num_reqs;
3430
 
    if (a->helptext) {
3431
 
      sz_strlcpy(packet.helptext, a->helptext);
3432
 
    } else {
3433
 
      packet.helptext[0] = '\0';
3434
 
    }
 
3605
    PACKET_STRVEC_COMPUTE(packet.helptext, a->helptext);
3435
3606
 
3436
3607
    lsend_packet_ruleset_tech(dest, &packet);
3437
3608
  } advance_iterate_end;
3449
3620
 
3450
3621
    packet.id = improvement_number(b);
3451
3622
    packet.genus = b->genus;
3452
 
    sz_strlcpy(packet.name, b->name.vernacular);
 
3623
    sz_strlcpy(packet.name, untranslated_name(&b->name));
 
3624
    sz_strlcpy(packet.rule_name, rule_name(&b->name));
3453
3625
    sz_strlcpy(packet.graphic_str, b->graphic_str);
3454
3626
    sz_strlcpy(packet.graphic_alt, b->graphic_alt);
3455
3627
    j = 0;
3467
3639
    packet.flags = b->flags;
3468
3640
    sz_strlcpy(packet.soundtag, b->soundtag);
3469
3641
    sz_strlcpy(packet.soundtag_alt, b->soundtag_alt);
3470
 
 
3471
 
    if (b->helptext) {
3472
 
      sz_strlcpy(packet.helptext, b->helptext);
3473
 
    } else {
3474
 
      packet.helptext[0] = '\0';
3475
 
    }
 
3642
    PACKET_STRVEC_COMPUTE(packet.helptext, b->helptext);
3476
3643
 
3477
3644
    lsend_packet_ruleset_building(dest, &packet);
3478
3645
  } improvement_iterate_end;
3494
3661
    packet.id = terrain_number(pterrain);
3495
3662
    packet.native_to = pterrain->native_to;
3496
3663
 
3497
 
    sz_strlcpy(packet.name_orig, pterrain->name.vernacular);
 
3664
    sz_strlcpy(packet.name, untranslated_name(&pterrain->name));
 
3665
    sz_strlcpy(packet.rule_name, rule_name(&pterrain->name));
3498
3666
    sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
3499
3667
    sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
3500
3668
 
3534
3702
    packet.clean_fallout_time = pterrain->clean_fallout_time;
3535
3703
 
3536
3704
    packet.flags = pterrain->flags;
3537
 
 
3538
 
    if (pterrain->helptext) {
3539
 
      sz_strlcpy(packet.helptext, pterrain->helptext);
3540
 
    } else {
3541
 
      packet.helptext[0] = '\0';
3542
 
    }
 
3705
    PACKET_STRVEC_COMPUTE(packet.helptext, pterrain->helptext);
3543
3706
 
3544
3707
    lsend_packet_ruleset_terrain(dest, &packet);
3545
3708
  } terrain_type_iterate_end;
3555
3718
  resource_type_iterate (presource) {
3556
3719
    packet.id = resource_number(presource);
3557
3720
 
3558
 
    sz_strlcpy(packet.name_orig, presource->name.vernacular);
 
3721
    sz_strlcpy(packet.name, untranslated_name(&presource->name));
 
3722
    sz_strlcpy(packet.rule_name, rule_name(&presource->name));
3559
3723
    sz_strlcpy(packet.graphic_str, presource->graphic_str);
3560
3724
    sz_strlcpy(packet.graphic_alt, presource->graphic_alt);
3561
3725
 
3579
3743
    int j;
3580
3744
 
3581
3745
    packet.id = base_number(b);
3582
 
    sz_strlcpy(packet.name, b->name.vernacular);
 
3746
    sz_strlcpy(packet.name, untranslated_name(&b->name));
 
3747
    sz_strlcpy(packet.rule_name, rule_name(&b->name));
3583
3748
    sz_strlcpy(packet.graphic_str, b->graphic_str);
3584
3749
    sz_strlcpy(packet.graphic_alt, b->graphic_alt);
3585
3750
    sz_strlcpy(packet.activity_gfx, b->activity_gfx);
3601
3766
    packet.vision_invis_sq = b->vision_invis_sq;
3602
3767
 
3603
3768
    packet.flags = b->flags;
 
3769
    packet.conflicts = b->conflicts;
 
3770
 
 
3771
    PACKET_STRVEC_COMPUTE(packet.helptext, b->helptext);
3604
3772
 
3605
3773
    lsend_packet_ruleset_base(dest, &packet);
3606
3774
  } base_type_iterate_end;
3614
3782
{
3615
3783
  struct packet_ruleset_government gov;
3616
3784
  struct packet_ruleset_government_ruler_title title;
3617
 
  struct ruler_title *p_title;
3618
3785
  int j;
3619
3786
 
3620
 
  government_iterate(g) {
 
3787
  governments_iterate(g) {
3621
3788
    /* send one packet_government */
3622
3789
    gov.id = government_number(g);
3623
3790
 
3627
3794
    } requirement_vector_iterate_end;
3628
3795
    gov.reqs_count = j;
3629
3796
 
3630
 
    gov.num_ruler_titles = g->num_ruler_titles;
3631
 
 
3632
 
    sz_strlcpy(gov.name, g->name.vernacular);
 
3797
    sz_strlcpy(gov.name, untranslated_name(&g->name));
 
3798
    sz_strlcpy(gov.rule_name, rule_name(&g->name));
3633
3799
    sz_strlcpy(gov.graphic_str, g->graphic_str);
3634
3800
    sz_strlcpy(gov.graphic_alt, g->graphic_alt);
3635
 
    
3636
 
    if (g->helptext) {
3637
 
      sz_strlcpy(gov.helptext, g->helptext);
3638
 
    } else {
3639
 
      gov.helptext[0] = '\0';
3640
 
    }
3641
 
      
 
3801
    PACKET_STRVEC_COMPUTE(gov.helptext, g->helptext);
 
3802
 
3642
3803
    lsend_packet_ruleset_government(dest, &gov);
3643
 
    
3644
 
    /* send one packet_government_ruler_title per ruler title */
3645
 
    for(j=0; j<g->num_ruler_titles; j++) {
3646
 
      p_title = &g->ruler_titles[j];
 
3804
 
 
3805
    /* Send one packet_government_ruler_title per ruler title. */
 
3806
    ruler_titles_iterate(government_ruler_titles(g), pruler_title) {
 
3807
      const struct nation_type *pnation = ruler_title_nation(pruler_title);
3647
3808
 
3648
3809
      title.gov = government_number(g);
3649
 
      title.id = j;
3650
 
      title.nation = p_title->nation ? nation_number(p_title->nation) : -1;
3651
 
      sz_strlcpy(title.male_title, p_title->male.vernacular);
3652
 
      sz_strlcpy(title.female_title, p_title->female.vernacular);
3653
 
    
 
3810
      title.nation = (NULL != pnation ? nation_number(pnation) : -1);
 
3811
      sz_strlcpy(title.male_title,
 
3812
                 ruler_title_male_untranslated_name(pruler_title));
 
3813
      sz_strlcpy(title.female_title,
 
3814
                 ruler_title_female_untranslated_name(pruler_title));
3654
3815
      lsend_packet_ruleset_government_ruler_title(dest, &title);
3655
 
    }
3656
 
  } government_iterate_end;
 
3816
    } ruler_titles_iterate_end;
 
3817
  } governments_iterate_end;
3657
3818
}
3658
3819
 
3659
3820
/**************************************************************************
3667
3828
  int i;
3668
3829
 
3669
3830
  groups_packet.ngroups = nation_group_count();
 
3831
  i = 0;
3670
3832
  nation_groups_iterate(pgroup) {
3671
 
    sz_strlcpy(groups_packet.groups[nation_group_index(pgroup)], pgroup->name);
 
3833
    sz_strlcpy(groups_packet.groups[i++],
 
3834
               nation_group_untranslated_name(pgroup));
3672
3835
  } nation_groups_iterate_end;
3673
3836
  lsend_packet_ruleset_nation_groups(dest, &groups_packet);
3674
3837
 
3675
 
  assert(sizeof(packet.init_techs)
3676
 
         == FC_MEMBER_SIZEOF(struct nation_type, init_techs));
3677
 
  assert(ARRAY_SIZE(packet.init_techs)
3678
 
         == FC_MEMBER_ARRAY_SIZE(struct nation_type, init_techs));
3679
 
 
3680
3838
  nations_iterate(n) {
3681
3839
    packet.id = nation_number(n);
3682
 
    sz_strlcpy(packet.adjective, n->adjective.vernacular);
3683
 
    sz_strlcpy(packet.noun_plural, n->noun_plural.vernacular);
 
3840
    sz_strlcpy(packet.adjective, untranslated_name(&n->adjective));
 
3841
    sz_strlcpy(packet.rule_name, rule_name(&n->adjective));
 
3842
    sz_strlcpy(packet.noun_plural, untranslated_name(&n->noun_plural));
3684
3843
    sz_strlcpy(packet.graphic_str, n->flag_graphic_str);
3685
3844
    sz_strlcpy(packet.graphic_alt, n->flag_graphic_alt);
3686
 
    packet.leader_count = n->leader_count;
3687
 
    for(i=0; i < n->leader_count; i++) {
3688
 
      sz_strlcpy(packet.leader_name[i], n->leaders[i].name);
3689
 
      packet.leader_sex[i] = n->leaders[i].is_male;
3690
 
    }
 
3845
 
 
3846
    i = 0;
 
3847
    nation_leader_list_iterate(nation_leaders(n), pleader) {
 
3848
      sz_strlcpy(packet.leader_name[i], nation_leader_name(pleader));
 
3849
      packet.leader_is_male[i] = nation_leader_is_male(pleader);
 
3850
      i++;
 
3851
    } nation_leader_list_iterate_end;
 
3852
    packet.leader_count = i;
 
3853
 
3691
3854
    packet.city_style = n->city_style;
3692
3855
    packet.is_playable = n->is_playable;
3693
3856
    packet.is_available = n->is_available;
3694
3857
    packet.barbarian_type = n->barb_type;
3695
 
    memcpy(packet.init_techs, n->init_techs, sizeof(packet.init_techs));
3696
 
    memcpy(packet.init_buildings, n->init_buildings, 
3697
 
           sizeof(packet.init_buildings));
3698
 
    memcpy(packet.init_units, n->init_units, 
3699
 
           sizeof(packet.init_units));
3700
 
    packet.init_government = government_number(n->init_government);
3701
3858
 
3702
3859
    sz_strlcpy(packet.legend, n->legend);
3703
3860
 
3704
 
     /* client needs only the names */
3705
 
     packet.ngroups = n->num_groups;
3706
 
     for (i = 0; i < n->num_groups; i++) {
3707
 
       packet.groups[i] = nation_group_number(n->groups[i]);
3708
 
     }
 
3861
    i = 0;
 
3862
    nation_group_list_iterate(n->groups, pgroup) {
 
3863
      packet.groups[i++] = nation_group_number(pgroup);
 
3864
    } nation_group_list_iterate_end;
 
3865
    packet.ngroups = i;
3709
3866
 
3710
3867
    lsend_packet_ruleset_nation(dest, &packet);
3711
3868
  } nations_iterate_end;
3730
3887
    } requirement_vector_iterate_end;
3731
3888
    city_p.reqs_count = j;
3732
3889
 
3733
 
    sz_strlcpy(city_p.name, city_styles[k].name.vernacular);
 
3890
    sz_strlcpy(city_p.name, untranslated_name(&city_styles[k].name));
 
3891
    sz_strlcpy(city_p.rule_name, rule_name(&city_styles[k].name));
3734
3892
    sz_strlcpy(city_p.graphic, city_styles[k].graphic);
3735
3893
    sz_strlcpy(city_p.graphic_alt, city_styles[k].graphic_alt);
3736
3894
    sz_strlcpy(city_p.oceanic_graphic, city_styles[k].oceanic_graphic);
3755
3913
         sizeof(game.work_veteran_chance));
3756
3914
  memcpy(misc_p.veteran_chance, game.veteran_chance, 
3757
3915
         sizeof(game.veteran_chance));
3758
 
    
3759
 
  assert(sizeof(misc_p.global_init_techs) ==
3760
 
         sizeof(game.server.rgame.global_init_techs));
3761
 
  assert(ARRAY_SIZE(misc_p.global_init_techs) ==
3762
 
         ARRAY_SIZE(game.server.rgame.global_init_techs));
 
3916
 
 
3917
  fc_assert(sizeof(misc_p.global_init_techs)
 
3918
            == sizeof(game.server.rgame.global_init_techs));
 
3919
  fc_assert(ARRAY_SIZE(misc_p.global_init_techs)
 
3920
            == ARRAY_SIZE(game.server.rgame.global_init_techs));
3763
3921
  memcpy(misc_p.global_init_techs, game.server.rgame.global_init_techs,
3764
 
         sizeof(misc_p.global_init_techs));
 
3922
         sizeof(misc_p.global_init_techs));
3765
3923
 
3766
3924
  misc_p.default_specialist = DEFAULT_SPECIALIST;
3767
3925
 
3768
3926
  lsend_packet_ruleset_game(dest, &misc_p);
3769
3927
}
3770
3928
 
 
3929
/**************************************************************************
 
3930
  Send all team names defined in the ruleset file(s) to the
 
3931
  specified connections.
 
3932
**************************************************************************/
 
3933
static void send_ruleset_team_names(struct conn_list *dest)
 
3934
{
 
3935
  struct packet_team_name_info team_name_info_p;
 
3936
 
 
3937
  team_slots_iterate(tslot) {
 
3938
    const char *name = team_slot_defined_name(tslot);
 
3939
 
 
3940
    if (NULL == name) {
 
3941
      /* End of defined names. */
 
3942
      break;
 
3943
    }
 
3944
 
 
3945
    team_name_info_p.team_id = team_slot_index(tslot);
 
3946
    sz_strlcpy(team_name_info_p.team_name, name);
 
3947
 
 
3948
    lsend_packet_team_name_info(dest, &team_name_info_p);
 
3949
  } team_slots_iterate_end;
 
3950
}
 
3951
 
3771
3952
/****************************************************************************
3772
3953
  HACK: reset any nations that have been set so far.
3773
3954
 
3793
3974
**************************************************************************/
3794
3975
void load_rulesets(void)
3795
3976
{
3796
 
  struct section_file techfile, unitfile, buildfile, govfile, terrfile;
3797
 
  struct section_file cityfile, nationfile, effectfile;
 
3977
  struct section_file *techfile, *unitfile, *buildfile, *govfile, *terrfile;
 
3978
  struct section_file *cityfile, *nationfile, *effectfile;
3798
3979
 
3799
 
  freelog(LOG_NORMAL, _("Loading rulesets"));
 
3980
  log_normal(_("Loading rulesets."));
3800
3981
 
3801
3982
  game_ruleset_free();
3802
3983
  game_ruleset_init();
3804
3985
  reset_player_nations();
3805
3986
  server.playable_nations = 0;
3806
3987
 
3807
 
  openload_ruleset_file(&techfile, "techs");
3808
 
  load_tech_names(&techfile);
3809
 
 
3810
 
  openload_ruleset_file(&buildfile, "buildings");
3811
 
  load_building_names(&buildfile);
3812
 
 
3813
 
  openload_ruleset_file(&govfile, "governments");
3814
 
  load_government_names(&govfile);
3815
 
 
3816
 
  openload_ruleset_file(&unitfile, "units");
3817
 
  load_unit_names(&unitfile);
3818
 
 
3819
 
  openload_ruleset_file(&terrfile, "terrain");
3820
 
  load_terrain_names(&terrfile);
3821
 
 
3822
 
  openload_ruleset_file(&cityfile, "cities");
3823
 
  load_citystyle_names(&cityfile);
3824
 
 
3825
 
  openload_ruleset_file(&nationfile, "nations");
3826
 
  load_nation_names(&nationfile);
3827
 
 
3828
 
  openload_ruleset_file(&effectfile, "effects");
3829
 
 
3830
 
  load_ruleset_techs(&techfile);
3831
 
  load_ruleset_cities(&cityfile);
3832
 
  load_ruleset_governments(&govfile);
3833
 
  load_ruleset_units(&unitfile);
3834
 
  load_ruleset_terrain(&terrfile);    /* terrain must precede nations */
3835
 
  load_ruleset_buildings(&buildfile);
3836
 
  load_ruleset_nations(&nationfile);
3837
 
  load_ruleset_effects(&effectfile);
 
3988
  techfile = openload_ruleset_file("techs");
 
3989
  load_tech_names(techfile);
 
3990
 
 
3991
  buildfile = openload_ruleset_file("buildings");
 
3992
  load_building_names(buildfile);
 
3993
 
 
3994
  govfile = openload_ruleset_file("governments");
 
3995
  load_government_names(govfile);
 
3996
 
 
3997
  unitfile = openload_ruleset_file("units");
 
3998
  load_unit_names(unitfile);
 
3999
 
 
4000
  terrfile = openload_ruleset_file("terrain");
 
4001
  load_terrain_names(terrfile);
 
4002
 
 
4003
  cityfile = openload_ruleset_file("cities");
 
4004
  load_citystyle_names(cityfile);
 
4005
 
 
4006
  nationfile = openload_ruleset_file("nations");
 
4007
  load_nation_names(nationfile);
 
4008
 
 
4009
  effectfile = openload_ruleset_file("effects");
 
4010
 
 
4011
  load_ruleset_techs(techfile);
 
4012
  load_ruleset_cities(cityfile);
 
4013
  load_ruleset_governments(govfile);
 
4014
  load_ruleset_units(unitfile);
 
4015
  load_ruleset_terrain(terrfile);    /* terrain must precede nations */
 
4016
  load_ruleset_buildings(buildfile);
 
4017
  load_ruleset_nations(nationfile);
 
4018
  load_ruleset_effects(effectfile);
3838
4019
  load_ruleset_game();
3839
4020
 
3840
4021
  /* Init nations we just loaded. */
3869
4050
  /* We may need to adjust the number of AI players
3870
4051
   * if the number of available nations changed. */
3871
4052
  if (game.info.aifill > server.playable_nations) {
3872
 
    freelog(LOG_NORMAL, _("Reducing aifill because there "
3873
 
                          "are not enough playable nations."));
 
4053
    log_normal(_("Reducing aifill because there "
 
4054
                 "are not enough playable nations."));
3874
4055
    game.info.aifill = server.playable_nations;
3875
4056
    aifill(game.info.aifill);
3876
4057
  }
3877
4058
}
3878
4059
 
3879
4060
/**************************************************************************
 
4061
  Reload the game settings saved in the ruleset file.
 
4062
**************************************************************************/
 
4063
void reload_rulesets_settings(void)
 
4064
{
 
4065
  struct section_file *file;
 
4066
 
 
4067
  file = openload_ruleset_file("game");
 
4068
  settings_ruleset(file, "settings");
 
4069
  secfile_destroy(file);
 
4070
}
 
4071
 
 
4072
/**************************************************************************
3880
4073
  Send all ruleset information to the specified connections.
3881
4074
**************************************************************************/
3882
4075
void send_rulesets(struct conn_list *dest)
3883
4076
{
3884
 
  conn_list_do_buffer(dest);
3885
 
  lsend_packet_freeze_hint(dest);
 
4077
  conn_list_compression_freeze(dest);
3886
4078
 
3887
4079
  send_ruleset_control(dest);
3888
4080
  send_ruleset_game(dest);
 
4081
  send_ruleset_team_names(dest);
3889
4082
  send_ruleset_techs(dest);
3890
4083
  send_ruleset_governments(dest);
3891
4084
  send_ruleset_unit_classes(dest);
3899
4092
  send_ruleset_cities(dest);
3900
4093
  send_ruleset_cache(dest);
3901
4094
 
3902
 
  lsend_packet_thaw_hint(dest);
3903
 
  conn_list_do_unbuffer(dest);
 
4095
  /* changed game settings will be send in
 
4096
   * connecthand.c:establish_new_connection() */
 
4097
 
 
4098
  conn_list_compression_thaw(dest);
3904
4099
}
3905
4100
 
3906
4101
/**************************************************************************
3921
4116
 
3922
4117
  /* See if it's given as national init tech */
3923
4118
  for (i = 0;
3924
 
       i < MAX_NUM_TECH_LIST && pnation->init_techs[i] != A_LAST;
 
4119
       i < MAX_NUM_TECH_LIST && pnation->server.init_techs[i] != A_LAST;
3925
4120
       i++) {
3926
 
    if (pnation->init_techs[i] == advance_number(tech)) {
 
4121
    if (pnation->server.init_techs[i] == advance_number(tech)) {
3927
4122
      return TRUE;
3928
4123
    }
3929
4124
  }
3939
4134
{
3940
4135
  int rc;
3941
4136
 
3942
 
  assert(preq->source.kind >= 0 && preq->source.kind < VUT_LAST);
 
4137
  fc_assert_ret_val(universals_n_is_valid(preq->source.kind), FALSE);
3943
4138
 
3944
4139
  /* Add to counter */
3945
4140
  reqs_of_type[preq->source.kind]++;
3965
4160
        * Requirements might be identical, but we consider multiple
3966
4161
        * declarations error anyway. */
3967
4162
 
3968
 
       freelog(LOG_ERROR,
3969
 
               "%s: Requirement list has multiple %s requirements",
3970
 
               list_for,
3971
 
               universal_type_rule_name(&preq->source));
 
4163
       log_error("%s: Requirement list has multiple %s requirements",
 
4164
                 list_for, universal_type_rule_name(&preq->source));
3972
4165
       return FALSE;
3973
4166
       break;
3974
4167
 
3977
4170
     case VUT_BASE:
3978
4171
       /* There can be only up to max_tiles requirements of these types */
3979
4172
       if (max_tiles != 1 && rc > max_tiles) {
3980
 
         freelog(LOG_ERROR,
3981
 
                 "%s: Requirement list has more %s requirements than "
3982
 
                 "can ever be fullfilled.",
3983
 
                 list_for,
3984
 
                 universal_type_rule_name(&preq->source));
 
4173
         log_error("%s: Requirement list has more %s requirements than "
 
4174
                   "can ever be fullfilled.", list_for,
 
4175
                   universal_type_rule_name(&preq->source));
3985
4176
         return FALSE;
3986
4177
       }
3987
4178
       break;
3993
4184
     case VUT_UCFLAG:
3994
4185
       /* Can have multiple requirements of these types */
3995
4186
       break;
3996
 
     case VUT_LAST:
 
4187
     case VUT_COUNT:
3997
4188
       /* Should never be in requirement vector */
3998
 
       assert(FALSE);
 
4189
       fc_assert(FALSE);
3999
4190
       return FALSE;
4000
4191
       break;
4001
4192
       /* No default handling here, as we want compiler warning
4024
4215
                                  int max_tiles,
4025
4216
                                  const char *list_for)
4026
4217
{
4027
 
  int reqs_of_type[VUT_LAST];
 
4218
  int reqs_of_type[VUT_COUNT];
4028
4219
 
4029
4220
  /* Initialize requirement counters */
4030
4221
  memset(reqs_of_type, 0, sizeof(reqs_of_type));
4046
4237
                                 int max_tiles,
4047
4238
                                 const char *list_for)
4048
4239
{
4049
 
  int reqs_of_type[VUT_LAST];
 
4240
  int reqs_of_type[VUT_COUNT];
4050
4241
 
4051
4242
  /* Initialize requirement counters */
4052
4243
  memset(reqs_of_type, 0, sizeof(reqs_of_type));
4082
4273
    requirement_list_iterate(preqs, preq) {
4083
4274
      requirement_list_iterate(pnreqs, pnreq) {
4084
4275
        if (are_requirements_equal(preq, pnreq)) {
4085
 
          freelog(LOG_ERROR,
4086
 
                  "%s: Identical %s requirement in requirements and negated requirements.",
4087
 
                  list_for,
4088
 
                  universal_type_rule_name(&preq->source));
 
4276
          log_error("%s: Identical %s requirement in requirements and "
 
4277
                    "negated requirements.", list_for,
 
4278
                    universal_type_rule_name(&preq->source));
4089
4279
          return FALSE;
4090
4280
        }
4091
4281
      } requirement_list_iterate_end;
4151
4341
 
4152
4342
    /* Check national initial techs */
4153
4343
    for (i = 0;
4154
 
         i < MAX_NUM_TECH_LIST && pnation->init_techs[i] != A_LAST;
 
4344
         i < MAX_NUM_TECH_LIST && pnation->server.init_techs[i] != A_LAST;
4155
4345
         i++) {
4156
 
      Tech_type_id tech = pnation->init_techs[i];
 
4346
      Tech_type_id tech = pnation->server.init_techs[i];
4157
4347
      struct advance *a = valid_advance_by_number(tech);
4158
4348
 
4159
4349
      if (!a) {
4212
4402
  } improvement_iterate_end;
4213
4403
 
4214
4404
  /* Governments */
4215
 
  government_iterate(pgov) {
 
4405
  governments_iterate(pgov) {
4216
4406
    if (!sanity_check_req_vec(&pgov->reqs, -1,
4217
4407
                              government_rule_name(pgov))) {
4218
4408
      ruleset_error(LOG_FATAL, "Governments have conflicting requirements!");
4219
4409
      ok = FALSE;
4220
4410
    }
4221
 
  } government_iterate_end;
 
4411
  } governments_iterate_end;
4222
4412
 
4223
4413
  /* Specialists */
4224
4414
  specialist_type_iterate(sp) {