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

« back to all changes in this revision

Viewing changes to server/ruleset.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2010-02-23 22:09:02 UTC
  • mfrom: (7.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20100223220902-s3spqi1x4e190y0t
[ Karl Goetz ]
* Remove civserver files in /etc/ggzd/ (Closes: 523772, 517787)
* Adding ${misc:Depends} to all binary packages (lintian warnings)

[ Clint Adams ]
* New upstream version.
  - Drop data_dsc_use_bindir.diff (binary pathnames have changed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#endif
17
17
 
18
18
#include <assert.h>
 
19
#include <stdarg.h>
19
20
#include <stdio.h>
20
21
#include <stdlib.h>
21
22
#include <string.h>
22
23
 
 
24
/* utility */
 
25
#include "fcintl.h"
 
26
#include "log.h"
 
27
#include "mem.h"
 
28
#include "registry.h"
 
29
#include "shared.h"
 
30
#include "support.h"
 
31
 
 
32
/* common */
 
33
#include "base.h"
23
34
#include "capability.h"
24
35
#include "city.h"
25
 
#include "fcintl.h"
 
36
#include "effects.h"
26
37
#include "game.h"
27
38
#include "government.h"
28
 
#include "log.h"
29
39
#include "map.h"
30
 
#include "mem.h"
31
40
#include "movement.h"
32
41
#include "nation.h"
33
42
#include "packets.h"
34
 
#include "registry.h"
35
43
#include "requirements.h"
36
 
#include "shared.h"
37
 
#include "support.h"
 
44
#include "specialist.h"
38
45
#include "tech.h"
39
46
#include "unit.h"
40
47
 
 
48
/* server */
41
49
#include "citytools.h"
42
50
#include "plrhand.h"
43
51
#include "script.h"
59
67
#define NATION_GROUP_SECTION_PREFIX "ngroup" /* without underscore? */
60
68
#define NATION_SECTION_PREFIX "nation" /* without underscore? */
61
69
#define RESOURCE_SECTION_PREFIX "resource_"
 
70
#define BASE_SECTION_PREFIX "base_"
62
71
#define SPECIALIST_SECTION_PREFIX "specialist_"
 
72
#define TERRAIN_CAPABILITY "+1.9+2007.Oct.26"
63
73
#define TERRAIN_SECTION_PREFIX "terrain_"
 
74
#define UNIT_CLASS_SECTION_PREFIX "unitclass_"
64
75
#define UNIT_SECTION_PREFIX "unit_"
65
76
 
66
77
static const char name_too_long[] = "Name \"%s\" too long; truncating.";
67
78
#define check_name(name) (check_strlen(name, MAX_LEN_NAME, name_too_long))
68
 
#define name_strlcpy(dst, src) ((void) sz_loud_strlcpy(dst, src, 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
#define MAX_SECTION_LABEL 64
 
84
#define section_strlcpy(dst, src) \
 
85
        (void) loud_strlcpy(dst, src, MAX_SECTION_LABEL, name_too_long)
 
86
static char *resource_sections = NULL;
 
87
static char *terrain_sections = NULL;
 
88
static char *base_sections = NULL;
 
89
 
69
90
 
70
91
static void openload_ruleset_file(struct section_file *file,
71
92
                                  const char *whichset);
73
94
                                        const char *us_capstr,
74
95
                                        const char *filename);
75
96
 
76
 
static int lookup_tech(struct section_file *file, const char *prefix,
77
 
                       const char *entry, bool required, const char *filename,
78
 
                       const char *description);
79
 
static void lookup_tech_list(struct section_file *file, const char *prefix,
80
 
                             const char *entry, int *output, const char *filename);
81
 
static struct unit_type *lookup_unit_type(struct section_file *file,
82
 
                                          const char *prefix,
83
 
                                          const char *entry, bool required,
84
 
                                          const char *filename,
85
 
                                          const char *description);
86
 
static Impr_type_id lookup_impr_type(struct section_file *file, const char *prefix,
87
 
                                     const char *entry, bool required,
88
 
                                     const char *filename, const char *description);
89
 
static char *lookup_helptext(struct section_file *file, char *prefix);
90
 
 
91
 
static struct terrain *lookup_terrain(char *name, struct terrain *tthis);
92
 
 
93
97
static void load_tech_names(struct section_file *file);
94
98
static void load_unit_names(struct section_file *file);
95
99
static void load_building_names(struct section_file *file);
96
100
static void load_government_names(struct section_file *file);
97
 
static void load_names(struct section_file *file);
 
101
static void load_terrain_names(struct section_file *file);
98
102
static void load_citystyle_names(struct section_file *file);
99
103
static void load_nation_names(struct section_file *file);
100
104
static struct nation_city* load_city_name_list(struct section_file *file,
112
116
static void load_ruleset_game(void);
113
117
 
114
118
static void send_ruleset_techs(struct conn_list *dest);
 
119
static void send_ruleset_unit_classes(struct conn_list *dest);
115
120
static void send_ruleset_units(struct conn_list *dest);
116
121
static void send_ruleset_buildings(struct conn_list *dest);
117
122
static void send_ruleset_terrain(struct conn_list *dest);
118
123
static void send_ruleset_resources(struct conn_list *dest);
 
124
static void send_ruleset_bases(struct conn_list *dest);
119
125
static void send_ruleset_governments(struct conn_list *dest);
120
126
static void send_ruleset_cities(struct conn_list *dest);
121
127
static void send_ruleset_game(struct conn_list *dest);
122
128
 
123
129
static bool nation_has_initial_tech(struct nation_type *pnation,
124
 
                                    Tech_type_id tech);
 
130
                                    struct advance *tech);
125
131
static bool sanity_check_ruleset_data(void);
 
132
static void ruleset_error(int loglevel, const char *format, ...)
 
133
                          fc__attribute((__format__ (__printf__, 2, 3)));
 
134
 
 
135
/**************************************************************************
 
136
  Notifications about ruleset errors to clients. Especially important in
 
137
  case of internal server crashing.
 
138
**************************************************************************/
 
139
static void ruleset_error(int loglevel, const char *format, ...)
 
140
{
 
141
  va_list args;
 
142
 
 
143
  va_start(args, format);
 
144
 
 
145
  vreal_freelog(loglevel, format, args);
 
146
 
 
147
  va_end(args);
 
148
 
 
149
  if (LOG_FATAL >= loglevel) {
 
150
    exit(EXIT_FAILURE);
 
151
  }
 
152
}
126
153
 
127
154
/**************************************************************************
128
155
  datafilename() wrapper: tries to match in two ways.
158
185
  if (dfilename) {
159
186
    return dfilename;
160
187
  } else {
161
 
    freelog(LOG_FATAL,
162
 
            /* TRANS: message about an installation error. */
163
 
            _("Could not find a readable \"%s.%s\" ruleset file."),
164
 
            name, extension);
165
 
    exit(EXIT_FAILURE);
 
188
    ruleset_error(LOG_FATAL,
 
189
                  /* TRANS: message about an installation error. */
 
190
                  _("Could not find a readable \"%s.%s\" ruleset file."),
 
191
                  name, extension);
166
192
  }
167
193
 
168
194
  return(NULL);
171
197
/**************************************************************************
172
198
  Do initial section_file_load on a ruleset file.
173
199
  "whichset" = "techs", "units", "buildings", "terrain", ...
174
 
  Calls exit(EXIT_FAILURE) on failure.
175
200
**************************************************************************/
176
201
static void openload_ruleset_file(struct section_file *file,
177
202
                                  const char *whichset)
178
203
{
179
204
  char sfilename[512];
180
 
  char *dfilename = valid_ruleset_filename(game.rulesetdir,
 
205
  char *dfilename = valid_ruleset_filename(game.server.rulesetdir,
181
206
                                           whichset, RULES_SUFFIX);
182
207
 
183
208
  /* Need to save a copy of the filename for following message, since
186
211
  sz_strlcpy(sfilename, dfilename);
187
212
 
188
213
  if (!section_file_load_nodup(file, sfilename)) {
189
 
    freelog(LOG_FATAL, "\"%s\": could not load ruleset.",
190
 
            sfilename);
191
 
    exit(EXIT_FAILURE);
 
214
    ruleset_error(LOG_FATAL, "\"%s\": could not load ruleset.",
 
215
                  sfilename);
192
216
  }
193
217
}
194
218
 
195
219
/**************************************************************************
196
220
  Parse script file.
197
 
  Calls exit(EXIT_FAILURE) on failure.
198
221
**************************************************************************/
199
222
static void openload_script_file(const char *whichset)
200
223
{
201
 
  char *dfilename = valid_ruleset_filename(game.rulesetdir,
 
224
  char *dfilename = valid_ruleset_filename(game.server.rulesetdir,
202
225
                                           whichset, SCRIPT_SUFFIX);
203
226
 
204
227
  if (!script_do_file(dfilename)) {
205
 
    freelog(LOG_FATAL, "\"%s\": could not load ruleset script.",
206
 
            dfilename);
207
 
    exit(EXIT_FAILURE);
 
228
    ruleset_error(LOG_FATAL, "\"%s\": could not load ruleset script.",
 
229
                  dfilename);
208
230
  }
209
231
}
210
232
 
224
246
                        filename);
225
247
    freelog(LOG_FATAL, "  datafile options: %s", datafile_options);
226
248
    freelog(LOG_FATAL, "  supported options: %s", us_capstr);
227
 
    exit(EXIT_FAILURE);
 
249
    ruleset_error(LOG_FATAL, "Capability problem");
228
250
  }
229
251
  if (!has_capabilities(datafile_options, us_capstr)) {
230
252
    freelog(LOG_FATAL, "\"%s\": ruleset datafile claims required option(s)"
231
253
                         " that we don't support:", filename);
232
254
    freelog(LOG_FATAL, "  datafile options: %s", datafile_options);
233
255
    freelog(LOG_FATAL, "  supported options: %s", us_capstr);
234
 
    exit(EXIT_FAILURE);
 
256
    ruleset_error(LOG_FATAL, "Capability problem");
235
257
  }
236
258
  return datafile_options;
237
259
}
271
293
        "%s.%s%d.negated", sec, sub, j);
272
294
 
273
295
    req = req_from_str(type, range, survives, negated, name);
274
 
    if (req.source.type == REQ_LAST) {
 
296
    if (VUT_LAST == req.source.kind) {
275
297
      /* Error.  Log it, clear the req and continue. */
276
298
      freelog(LOG_ERROR,
277
299
          "\"%s\" [%s] has unknown req: \"%s\" \"%s\".",
278
300
          filename, sec, type, name);
279
 
      req.source.type = REQ_NONE;
 
301
      req.source.kind = VUT_NONE;
280
302
    }
281
303
 
282
304
    requirement_vector_append(&list, &req);
283
305
  }
284
306
 
285
307
  if (j > MAX_NUM_REQS) {
286
 
    freelog(LOG_FATAL, "Too many (%d) requirements for %s. Max is %d",
287
 
            j, rfor, MAX_NUM_REQS);
288
 
    exit(EXIT_FAILURE);
 
308
    ruleset_error(LOG_FATAL, "Too many (%d) requirements for %s. Max is %d",
 
309
                  j, rfor, MAX_NUM_REQS);
289
310
  }
290
311
 
291
312
  return &list;
293
314
 
294
315
/**************************************************************************
295
316
 Lookup a string prefix.entry in the file and return the corresponding
296
 
 advances id.  If (!required), return A_LAST if match "Never" or can't match.
297
 
 If (required), die if can't match.  Note the first tech should have
298
 
 name "None" so that will always match.
 
317
 advances pointer.  If (!required), return A_NEVER for match "Never" or
 
318
 can't match.  If (required), die when can't match.  Note the first tech
 
319
 should have name "None" so that will always match.
299
320
 If description is not NULL, it is used in the warning message
300
321
 instead of prefix (eg pass unit->name instead of prefix="units2.u27")
301
322
**************************************************************************/
302
 
static int lookup_tech(struct section_file *file, const char *prefix,
303
 
                       const char *entry, bool required, const char *filename,
304
 
                       const char *description)
 
323
static struct advance *lookup_tech(struct section_file *file,
 
324
                                   const char *prefix, const char *entry,
 
325
                                   int loglevel, const char *filename,
 
326
                                   const char *description)
305
327
{
306
328
  char *sval;
307
 
  int i;
 
329
  struct advance *padvance;
308
330
  
309
331
  sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
310
 
  if (!sval || (!required && strcmp(sval, "Never") == 0)) {
311
 
    i = A_LAST;
 
332
  if (!sval || (LOG_FATAL < loglevel && strcmp(sval, "Never") == 0)) {
 
333
    padvance = A_NEVER;
312
334
  } else {
313
 
    i = find_advance_by_rule_name(sval);
314
 
    if (i==A_LAST) {
315
 
      freelog((required?LOG_FATAL:LOG_ERROR),
316
 
           "\"%s\" %s %s: couldn't match \"%s\".",
317
 
           filename, (description?description:prefix), entry, sval );
318
 
      if (required) {
319
 
        exit(EXIT_FAILURE);
320
 
      } else {
321
 
        i = A_LAST;
322
 
      }
 
335
    padvance = find_advance_by_rule_name(sval);
 
336
 
 
337
    if (A_NEVER == padvance) {
 
338
      ruleset_error(loglevel,
 
339
                    "\"%s\" %s %s: couldn't match \"%s\".",
 
340
                    filename, (description ? description : prefix), entry, sval);
 
341
 
 
342
      /* ruleset_error returned only if error was not fatal. */
323
343
    }
324
344
  }
325
 
  return i;
 
345
  return padvance;
326
346
}
327
347
 
328
348
/**************************************************************************
329
349
 Lookup a string prefix.entry in the file and return the corresponding
330
 
 buildings id.  If (!required), return A_LAST if match "Never" or can't match.
331
 
 If (required), die if can't match.  Note the first tech should have
332
 
 name "None" so that will always match.
 
350
 improvement pointer.  If (!required), return B_NEVER for match "None" or
 
351
 can't match.  If (required), die when can't match.
333
352
 If description is not NULL, it is used in the warning message
334
353
 instead of prefix (eg pass unit->name instead of prefix="units2.u27")
335
354
**************************************************************************/
336
 
static int lookup_building(struct section_file *file, const char *prefix,
337
 
                           const char *entry, bool required,
338
 
                           const char *filename, const char *description)
 
355
static struct impr_type *lookup_building(struct section_file *file,
 
356
                                         const char *prefix, const char *entry,
 
357
                                         int loglevel, const char *filename,
 
358
                                         const char *description)
339
359
{
340
360
  char *sval;
341
 
  int i;
 
361
  struct impr_type *pimprove;
342
362
  
343
363
  sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
344
 
  if ((!required && !sval) || strcmp(sval, "None") == 0) {
345
 
    i = B_LAST;
 
364
  if (!sval || (LOG_FATAL < loglevel && strcmp(sval, "None") == 0)) {
 
365
    pimprove = B_NEVER;
346
366
  } else {
347
 
    i = find_improvement_by_rule_name(sval);
348
 
    if (i == B_LAST) {
349
 
      freelog((required?LOG_FATAL:LOG_ERROR),
350
 
           "\"%s\" %s %s: couldn't match \"%s\".",
351
 
           filename, (description?description:prefix), entry, sval );
352
 
      if (required) {
353
 
        exit(EXIT_FAILURE);
354
 
      } else {
355
 
        i = B_LAST;
356
 
      }
 
367
    pimprove = find_improvement_by_rule_name(sval);
 
368
 
 
369
    if (B_NEVER == pimprove) {
 
370
      ruleset_error(loglevel,
 
371
                    "\"%s\" %s %s: couldn't match \"%s\".",
 
372
                    filename, (description ? description : prefix), entry, sval);
 
373
 
 
374
      /* ruleset_error() returned only if error was not fatal */
357
375
    }
358
376
  }
359
 
  return i;
 
377
  return pimprove;
360
378
}
361
379
 
362
380
/**************************************************************************
367
385
 we report it as an error, otherwise we just punt.
368
386
**************************************************************************/
369
387
static void lookup_unit_list(struct section_file *file, const char *prefix,
370
 
                             const char *entry, struct unit_type **output, 
371
 
                             const char *filename, bool required)
 
388
                             const char *entry, int loglevel,
 
389
                             struct unit_type **output, 
 
390
                             const char *filename)
372
391
{
373
392
  char **slist;
374
393
  int i, nval;
379
398
  }
380
399
  slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
381
400
  if (nval == 0) {
382
 
    if (required) {
383
 
      freelog(LOG_FATAL, "\"%s\": missing string vector %s.%s",
384
 
              filename, prefix, entry);
385
 
      exit(EXIT_FAILURE);
 
401
    if (LOG_FATAL >= loglevel) {
 
402
      ruleset_error(LOG_FATAL, "\"%s\": missing string vector %s.%s",
 
403
                    filename, prefix, entry);
386
404
    }
387
405
    return;
388
406
  }
389
407
  if (nval > MAX_NUM_UNIT_LIST) {
390
 
    freelog(LOG_FATAL, "\"%s\": string vector %s.%s too long (%d, max %d)",
391
 
            filename, prefix, entry, nval, MAX_NUM_UNIT_LIST);
392
 
    exit(EXIT_FAILURE);
 
408
    ruleset_error(LOG_FATAL,
 
409
                  "\"%s\": string vector %s.%s too long (%d, max %d)",
 
410
                  filename, prefix, entry, nval, MAX_NUM_UNIT_LIST);
393
411
  }
394
412
  if (nval == 1 && strcmp(slist[0], "") == 0) {
395
413
    free(slist);
400
418
    struct unit_type *punittype = find_unit_type_by_rule_name(sval);
401
419
 
402
420
    if (!punittype) {
403
 
      freelog(LOG_FATAL, "\"%s\" %s.%s (%d): couldn't match \"%s\".",
404
 
              filename, prefix, entry, i, sval);
405
 
      exit(EXIT_FAILURE);
 
421
      ruleset_error(LOG_FATAL,
 
422
                    "\"%s\" %s.%s (%d): couldn't match \"%s\".",
 
423
                    filename, prefix, entry, i, sval);
406
424
    }
407
425
    output[i] = punittype;
408
 
    freelog(LOG_DEBUG, "%s.%s,%d %s %d", prefix, entry, i, sval,
409
 
            punittype->index);
 
426
    freelog(LOG_DEBUG, "\"%s\" %s.%s (%d): %s (%d)",
 
427
            filename, prefix, entry, i, sval,
 
428
            utype_number(punittype));
410
429
  }
411
430
  free(slist);
412
431
  return;
417
436
 array, which should hold MAX_NUM_TECH_LIST items. The output array is
418
437
 either A_LAST terminated or full (contains MAX_NUM_TECH_LIST
419
438
 items). All valid entries of the output array are guaranteed to
420
 
 tech_exist(). There should be at least one value, but it may be "",
 
439
 exist. There should be at least one value, but it may be "",
421
440
 meaning empty list.
422
441
**************************************************************************/
423
442
static void lookup_tech_list(struct section_file *file, const char *prefix,
432
451
  }
433
452
  slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
434
453
  if (nval==0) {
435
 
    freelog(LOG_FATAL, "\"%s\": missing string vector %s.%s",
436
 
            filename, prefix, entry);
437
 
    exit(EXIT_FAILURE);
 
454
    ruleset_error(LOG_FATAL, "\"%s\": missing string vector %s.%s",
 
455
                  filename, prefix, entry);
438
456
  }
439
457
  if (nval>MAX_NUM_TECH_LIST) {
440
 
    freelog(LOG_FATAL, "\"%s\": string vector %s.%s too long (%d, max %d)",
441
 
            filename, prefix, entry, nval, MAX_NUM_TECH_LIST);
442
 
    exit(EXIT_FAILURE);
 
458
    ruleset_error(LOG_FATAL,
 
459
                  "\"%s\": string vector %s.%s too long (%d, max %d)",
 
460
                  filename, prefix, entry, nval, MAX_NUM_TECH_LIST);
443
461
  }
444
462
  if (nval==1 && strcmp(slist[0], "")==0) {
445
463
    free(slist);
447
465
  }
448
466
  for (i=0; i<nval; i++) {
449
467
    char *sval = slist[i];
450
 
    int tech = find_advance_by_rule_name(sval);
451
 
    if (tech==A_LAST) {
452
 
      freelog(LOG_FATAL, "\"%s\" %s.%s (%d): couldn't match \"%s\".",
453
 
              filename, prefix, entry, i, sval);
454
 
      exit(EXIT_FAILURE);
455
 
    }
456
 
    if (!tech_exists(tech)) {
457
 
      freelog(LOG_FATAL, "\"%s\" %s.%s (%d): \"%s\" is removed.",
458
 
              filename, prefix, entry, i, sval);
459
 
      exit(EXIT_FAILURE);
460
 
    }
461
 
    output[i] = tech;
462
 
    freelog(LOG_DEBUG, "%s.%s,%d %s %d", prefix, entry, i, sval, tech);
 
468
    struct advance *padvance = find_advance_by_rule_name(sval);
 
469
 
 
470
    if (NULL == padvance) {
 
471
      ruleset_error(LOG_FATAL,
 
472
                    "\"%s\" %s.%s (%d): couldn't match \"%s\".",
 
473
                    filename, prefix, entry, i, sval);
 
474
    }
 
475
    if (!valid_advance(padvance)) {
 
476
      ruleset_error(LOG_FATAL, "\"%s\" %s.%s (%d): \"%s\" is removed.",
 
477
                    filename, prefix, entry, i, sval);
 
478
    }
 
479
    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));
463
483
  }
464
484
  free(slist);
465
485
  return;
469
489
  Lookup a prefix.entry string vector in the file and fill in the
470
490
  array, which should hold MAX_NUM_BUILDING_LIST items. The output array is
471
491
  either B_LAST terminated or full (contains MAX_NUM_BUILDING_LIST
472
 
  items). All valid entries of the output array are guaranteed to pass
473
 
  improvement_exist(). There should be at least one value, but it may be
 
492
  items). [All valid entries of the output array are guaranteed to pass
 
493
  improvement_exist()?] There should be at least one value, but it may be
474
494
  "", meaning an empty list.
475
495
**************************************************************************/
476
496
static void lookup_building_list(struct section_file *file, const char *prefix,
486
506
  }
487
507
  slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
488
508
  if (nval == 0) {
489
 
    freelog(LOG_FATAL, "\"%s\": missing string vector %s.%s",
490
 
            filename, prefix, entry);
491
 
    exit(EXIT_FAILURE);
 
509
    ruleset_error(LOG_FATAL, "\"%s\": missing string vector %s.%s",
 
510
                  filename, prefix, entry);
492
511
  }
493
512
  if (nval > MAX_NUM_BUILDING_LIST) {
494
 
    freelog(LOG_FATAL, "\"%s\": string vector %s.%s too long (%d, max %d)",
495
 
            filename, prefix, entry, nval, MAX_NUM_BUILDING_LIST);
496
 
    exit(EXIT_FAILURE);
 
513
    ruleset_error(LOG_FATAL,
 
514
                  "\"%s\": string vector %s.%s too long (%d, max %d)",
 
515
                  filename, prefix, entry, nval, MAX_NUM_BUILDING_LIST);
497
516
  }
498
517
  if (nval == 1 && strcmp(slist[0], "") == 0) {
499
518
    free(slist);
501
520
  }
502
521
  for (i = 0; i < nval; i++) {
503
522
    char *sval = slist[i];
504
 
    int building = find_improvement_by_rule_name(sval);
 
523
    struct impr_type *pimprove = find_improvement_by_rule_name(sval);
505
524
 
506
 
    if (building == B_LAST) {
507
 
      freelog(LOG_FATAL, "\"%s\" %s.%s (%d): couldn't match \"%s\".",
508
 
              filename, prefix, entry, i, sval);
509
 
      exit(EXIT_FAILURE);
 
525
    if (NULL == pimprove) {
 
526
      ruleset_error(LOG_FATAL,
 
527
                    "\"%s\" %s.%s (%d): couldn't match \"%s\".",
 
528
                    filename, prefix, entry, i, sval);
510
529
    }
511
 
    output[i] = building;
512
 
    freelog(LOG_DEBUG, "%s.%s,%d %s %d", prefix, entry, i, sval, building);
 
530
    output[i] = improvement_number(pimprove);
 
531
    freelog(LOG_DEBUG, "%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
513
532
  }
514
533
  free(slist);
515
534
}
523
542
**************************************************************************/
524
543
static struct unit_type *lookup_unit_type(struct section_file *file,
525
544
                                          const char *prefix,
526
 
                                          const char *entry, bool required,
 
545
                                          const char *entry,
 
546
                                          int loglevel,
527
547
                                          const char *filename,
528
548
                                          const char *description)
529
549
{
530
550
  char *sval;
531
551
  struct unit_type *punittype;
532
552
  
533
 
  if (required) {
 
553
  if (LOG_FATAL >= loglevel) {
534
554
    sval = secfile_lookup_str(file, "%s.%s", prefix, entry);
535
555
  } else {
536
556
    sval = secfile_lookup_str_default(file, "None", "%s.%s", prefix, entry);
541
561
  } else {
542
562
    punittype = find_unit_type_by_rule_name(sval);
543
563
    if (!punittype) {
544
 
      freelog((required?LOG_FATAL:LOG_ERROR),
545
 
           "\"%s\" %s %s: couldn't match \"%s\".",
546
 
           filename, (description?description:prefix), entry, sval );
547
 
      if (required) {
548
 
        exit(EXIT_FAILURE);
549
 
      } else {
550
 
        punittype = NULL;
551
 
      }
 
564
      ruleset_error(loglevel,
 
565
                    "\"%s\" %s %s: couldn't match \"%s\".",
 
566
                    filename, (description ? description : prefix), entry, sval);
 
567
 
 
568
      /* We continue if error was not fatal. */
 
569
      punittype = NULL;
552
570
    }
553
571
  }
554
572
  return punittype;
555
573
}
556
574
 
557
575
/**************************************************************************
558
 
 Lookup a string prefix.entry in the file and return the corresponding
559
 
 Impr_type_id.  If (!required), return B_LAST if match "None" or can't match.
560
 
 If (required), die if can't match.
561
 
 If description is not NULL, it is used in the warning message
562
 
 instead of prefix (eg pass impr->name instead of prefix="imprs2.b27")
563
 
**************************************************************************/
564
 
static Impr_type_id lookup_impr_type(struct section_file *file, const char *prefix,
565
 
                                     const char *entry, bool required,
566
 
                                     const char *filename, const char *description)
567
 
{
568
 
  char *sval;
569
 
  Impr_type_id id;
570
 
 
571
 
  if (required) {
572
 
    sval = secfile_lookup_str(file, "%s.%s", prefix, entry);
573
 
  } else {
574
 
    sval = secfile_lookup_str_default(file, "None", "%s.%s", prefix, entry);
575
 
  }
576
 
 
577
 
  if (strcmp(sval, "None")==0) {
578
 
    id = B_LAST;
579
 
  } else {
580
 
    id = find_improvement_by_rule_name(sval);
581
 
    if (id==B_LAST) {
582
 
      freelog((required?LOG_FATAL:LOG_ERROR),
583
 
           "\"%s\" %s %s: couldn't match \"%s\".",
584
 
           filename, (description?description:prefix), entry, sval );
585
 
      if (required) {
586
 
        exit(EXIT_FAILURE);
587
 
      }
588
 
    }
589
 
  }
590
 
 
591
 
  return id;
592
 
}
593
 
 
594
 
/**************************************************************************
595
576
  Lookup entry in the file and return the corresponding government index;
596
577
  dies if can't find/match.  filename is for error message.
597
578
**************************************************************************/
605
586
  sval = secfile_lookup_str(file, "%s", entry);
606
587
  gov = find_government_by_rule_name(sval);
607
588
  if (!gov) {
608
 
    freelog(LOG_FATAL,
609
 
           "\"%s\" %s: couldn't match \"%s\".",
610
 
           filename, entry, sval );
611
 
    exit(EXIT_FAILURE);
 
589
    ruleset_error(LOG_FATAL,
 
590
                  "\"%s\" %s: couldn't match \"%s\".",
 
591
                  filename, entry, sval);
612
592
  }
613
593
  return gov;
614
594
}
615
595
 
616
596
/**************************************************************************
 
597
  Lookup entry in the file and return the corresponding move_type index;
 
598
  dies if can't find/match.  filename is for error message.
 
599
**************************************************************************/
 
600
static enum unit_move_type lookup_move_type(struct section_file *file,
 
601
                                            const char *entry,
 
602
                                            const char *filename)
 
603
{
 
604
  char *sval;
 
605
  enum unit_move_type mt;
 
606
  
 
607
  sval = secfile_lookup_str(file, "%s", entry);
 
608
  mt = move_type_from_str(sval);
 
609
  if (mt == MOVETYPE_LAST) {
 
610
    ruleset_error(LOG_FATAL,
 
611
                  "\"%s\" %s: couldn't match \"%s\".",
 
612
                  filename, entry, sval);
 
613
  }
 
614
  return mt;
 
615
}
 
616
 
 
617
/**************************************************************************
617
618
  Lookup optional string, returning allocated memory or NULL.
618
619
**************************************************************************/
619
620
static char *lookup_string(struct section_file *file, const char *prefix,
634
635
/**************************************************************************
635
636
  Lookup optional helptext, returning allocated memory or NULL.
636
637
**************************************************************************/
637
 
static char *lookup_helptext(struct section_file *file, char *prefix)
 
638
static char *lookup_helptext(struct section_file *file, const char *prefix)
638
639
{
639
640
  return lookup_string(file, prefix, "helptext");
640
641
}
641
642
 
642
643
/**************************************************************************
643
 
  Look up the terrain (untranslated) rule name and return its pointer.
644
 
**************************************************************************/
645
 
static struct terrain *lookup_terrain(char *name, struct terrain *tthis)
646
 
{
647
 
  if (*name == '\0' || (0 == strcmp(name, "none")) 
 
644
  Look up the resource section name and return its pointer.
 
645
**************************************************************************/
 
646
static struct resource *lookup_resource(const char *filename,
 
647
                                        const char *name,
 
648
                                        const char *jsection)
 
649
{
 
650
  resource_type_iterate(presource) {
 
651
    const int i = resource_index(presource);
 
652
    const char *isection = &resource_sections[i * MAX_SECTION_LABEL];
 
653
    if (0 == mystrcasecmp(isection, name)) {
 
654
      return presource;
 
655
    }
 
656
  } resource_type_iterate_end;
 
657
 
 
658
  ruleset_error(LOG_ERROR,
 
659
                "\"%s\" [%s] has unknown \"%s\".",
 
660
                filename,
 
661
                jsection,
 
662
                name);
 
663
  return NULL;
 
664
}
 
665
 
 
666
/**************************************************************************
 
667
  Look up the terrain section name and return its pointer.
 
668
**************************************************************************/
 
669
static struct terrain *lookup_terrain(struct section_file *file,
 
670
                                      const char *item,
 
671
                                      struct terrain *pthis)
 
672
{
 
673
  const int j = terrain_index(pthis);
 
674
  const char *jsection = &terrain_sections[j * MAX_SECTION_LABEL];
 
675
  char *name = secfile_lookup_str(file, "%s.%s", jsection, item);
 
676
 
 
677
  if (NULL == name
 
678
      || *name == '\0'
 
679
      || (0 == strcmp(name, "none"))
648
680
      || (0 == strcmp(name, "no"))) {
649
681
    return T_NONE;
650
 
  } else if (0 == strcmp(name, "yes")) {
651
 
    return (tthis);
 
682
  }
 
683
  if (0 == strcmp(name, "yes")) {
 
684
    return pthis;
652
685
  }
653
686
 
654
 
  /* find_terrain_by_rule_name plus error */
655
687
  terrain_type_iterate(pterrain) {
656
 
    if (0 == strcmp(name, terrain_rule_name(pterrain))) {
 
688
    const int i = terrain_index(pterrain);
 
689
    const char *isection = &terrain_sections[i * MAX_SECTION_LABEL];
 
690
    if (0 == mystrcasecmp(isection, name)) {
657
691
      return pterrain;
658
692
    }
659
693
  } terrain_type_iterate_end;
660
694
 
661
 
  freelog(LOG_ERROR, "\"%s\" has unknown terrain \"%s\".",
662
 
          terrain_rule_name(tthis),
663
 
          name);
 
695
  ruleset_error(LOG_ERROR,
 
696
                "\"%s\" [%s] has unknown \"%s\".",
 
697
                secfile_filename(file),
 
698
                jsection,
 
699
                name);
664
700
  return T_NONE;
665
701
}
666
702
 
670
706
static void load_tech_names(struct section_file *file)
671
707
{
672
708
  char **sec;
673
 
  struct advance *a;
674
709
  int num_techs; /* number of techs in the ruleset (means without A_NONE)*/
675
710
  int i;
676
711
  const char *filename = secfile_filename(file);
681
716
  sec = secfile_get_secnames_prefix(file, ADVANCE_SECTION_PREFIX, &num_techs);
682
717
  freelog(LOG_VERBOSE, "%d advances (including possibly unused)", num_techs);
683
718
  if(num_techs == 0) {
684
 
    freelog(LOG_FATAL, "\"%s\": No Advances?!?", filename);
685
 
    exit(EXIT_FAILURE);
 
719
    ruleset_error(LOG_FATAL, "\"%s\": No Advances?!?", filename);
686
720
  }
687
721
 
688
722
  if(num_techs + A_FIRST > A_LAST_REAL) {
689
 
    freelog(LOG_FATAL, "\"%s\": Too many advances (%d, max %d)",
690
 
            filename, num_techs, A_LAST_REAL-A_FIRST);
691
 
    exit(EXIT_FAILURE);
 
723
    ruleset_error(LOG_FATAL, "\"%s\": Too many advances (%d, max %d)",
 
724
                  filename, num_techs, A_LAST_REAL-A_FIRST);
692
725
  }
693
726
 
694
 
  game.control.num_tech_types = num_techs + 1; /* includes A_NONE */
 
727
  game.control.num_tech_types = num_techs + A_FIRST; /* includes A_NONE */
695
728
 
696
 
  a = &advances[A_FIRST];
697
 
  for (i = 0; i < num_techs; i++ ) {
 
729
  i = 0;
 
730
  advance_iterate(A_FIRST, a) {
698
731
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
699
732
    name_strlcpy(a->name.vernacular, name);
700
733
    a->name.translated = NULL;
701
 
    a++;
702
 
  }
 
734
    i++;
 
735
  } advance_iterate_end;
703
736
  free(sec);
704
737
}
705
738
 
709
742
static void load_ruleset_techs(struct section_file *file)
710
743
{
711
744
  char **sec;
712
 
  struct advance *a;
713
745
  int num_techs; /* number of techs in the ruleset (means without A_NONE)*/
714
746
  int i;
 
747
  struct advance *a_none = advance_by_number(A_NONE);
715
748
  const char *filename = secfile_filename(file);
716
749
  
717
750
  (void) check_ruleset_capabilities(file, "+1.9", filename);
718
751
  sec = secfile_get_secnames_prefix(file, ADVANCE_SECTION_PREFIX, &num_techs);
719
752
 
720
753
  /* Initialize dummy tech A_NONE */
721
 
  advances[A_NONE].req[0] = A_NONE;
722
 
  advances[A_NONE].req[1] = A_NONE;
723
 
  advances[A_NONE].flags = 0;
724
 
  advances[A_NONE].root_req = A_LAST;
 
754
  a_none->require[AR_ONE] = a_none;
 
755
  a_none->require[AR_TWO] = a_none;
 
756
  a_none->require[AR_ROOT] = A_NEVER;
 
757
  a_none->flags = 0;
725
758
 
726
 
  a = &advances[A_FIRST];
727
 
  
728
 
  for( i=0; i<num_techs; i++ ) {
 
759
  i = 0;
 
760
  advance_iterate(A_FIRST, a) {
729
761
    char *sval, **slist;
730
762
    int j,ival,nval;
731
763
 
732
 
    a->req[0] = lookup_tech(file, sec[i], "req1", FALSE,
733
 
                            filename, a->name.vernacular);
734
 
    a->req[1] = lookup_tech(file, sec[i], "req2", FALSE,
735
 
                            filename, a->name.vernacular);
736
 
    a->root_req = lookup_tech(file, sec[i], "root_req", FALSE,
737
 
                              filename, a->name.vernacular);
 
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);
738
770
 
739
 
    if ((a->req[0]==A_LAST && a->req[1]!=A_LAST) ||
740
 
        (a->req[0]!=A_LAST && a->req[1]==A_LAST)) {
 
771
    if ((A_NEVER == a->require[AR_ONE] && A_NEVER != a->require[AR_TWO])
 
772
     || (A_NEVER != a->require[AR_ONE] && A_NEVER == a->require[AR_TWO])) {
741
773
      freelog(LOG_ERROR, "\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
742
774
              filename,
743
775
              sec[i],
744
776
              a->name.vernacular);
745
 
      a->req[0] = a->req[1] = A_LAST;
 
777
      a->require[AR_ONE] = a->require[AR_TWO] = A_NEVER;
746
778
    }
747
 
    if (a->req[0]==A_NONE && a->req[1]!=A_NONE) {
 
779
    if (a_none == a->require[AR_ONE] && a_none != a->require[AR_TWO]) {
748
780
      freelog(LOG_ERROR, "\"%s\" [%s] \"%s\": should have \"None\" second.",
749
781
              filename,
750
782
              sec[i],
751
783
              a->name.vernacular);
752
 
      a->req[0] = a->req[1];
753
 
      a->req[1] = A_NONE;
 
784
      a->require[AR_ONE] = a->require[AR_TWO];
 
785
      a->require[AR_TWO] = a_none;
754
786
    }
755
787
 
756
788
    a->flags = 0;
768
800
                sec[i],
769
801
                a->name.vernacular,
770
802
                sval);
 
803
      } else {
 
804
        a->flags |= (1<<ival);
771
805
      }
772
 
      a->flags |= (1<<ival);
773
806
    }
774
807
    free(slist);
775
808
 
785
818
        secfile_lookup_int_default(file, -1, "%s.%s", sec[i], "cost");
786
819
    a->num_reqs = 0;
787
820
    
788
 
    a++;
789
 
  }
 
821
    i++;
 
822
  } advance_iterate_end;
790
823
 
791
824
  /* Propagate a root tech up into the tech tree.  Thus if a technology
792
825
   * X has Y has a root tech, then any technology requiring X also has
793
826
   * Y as a root tech. */
794
827
restart:
795
 
  for (i = A_FIRST; i < A_FIRST + num_techs; i++) {
796
 
    a = &advances[i];
797
 
    if (a->root_req != A_LAST && tech_exists(i)) {
798
 
      int j;
 
828
  advance_iterate(A_FIRST, a) {
 
829
    if (valid_advance(a)
 
830
     && A_NEVER != a->require[AR_ROOT]) {
799
831
      bool out_of_order = FALSE;
800
832
 
801
 
      /* Now find any tech depending on this technology and update it's
 
833
      /* Now find any tech depending on this technology and update its
802
834
       * root_req. */
803
 
      for(j = A_FIRST; j < A_FIRST + num_techs; j++) {
804
 
        struct advance *b = &advances[j];
805
 
        if ((b->req[0] == i || b->req[1] == i)
806
 
            && b->root_req == A_LAST
807
 
            && tech_exists(j)) {
808
 
          b->root_req = a->root_req;
809
 
          if (j < i) {
 
835
      advance_iterate(A_FIRST, b) {
 
836
        if (valid_advance(b)
 
837
         && A_NEVER == b->require[AR_ROOT]
 
838
         && (a == b->require[AR_ONE] || a == b->require[AR_TWO])) {
 
839
          b->require[AR_ROOT] = a->require[AR_ROOT];
 
840
          if (b < a) {
810
841
            out_of_order = TRUE;
811
842
          }
812
843
        }
813
 
      }
 
844
      } advance_iterate_end;
814
845
 
815
846
      if (out_of_order) {
816
847
        /* HACK: If we just changed the root_tech of a lower-numbered
819
850
        goto restart;   
820
851
      }
821
852
    }
822
 
  }
823
 
  /* Now rename A_LAST to A_NONE for consistency's sake */
824
 
  for (i = A_NONE; i < A_FIRST + num_techs; i++) {
825
 
    a = &advances[i];
826
 
    if (a->root_req == A_LAST) {
827
 
      a->root_req = A_NONE;
 
853
  } advance_iterate_end;
 
854
 
 
855
  /* Now rename A_NEVER to A_NONE for consistency */
 
856
  advance_iterate(A_NONE, a) {
 
857
    if (A_NEVER == a->require[AR_ROOT]) {
 
858
      a->require[AR_ROOT] = a_none;
828
859
    }
829
 
  }
 
860
  } advance_iterate_end;
830
861
 
831
862
  /* Some more consistency checking: 
832
863
     Non-removed techs depending on removed techs is too
833
864
     broken to fix by default, so die.
834
865
  */
835
 
  tech_type_iterate(i) {
836
 
    if (i != A_NONE && tech_exists(i)) {
837
 
      a = &advances[i];
 
866
  advance_iterate(A_FIRST, a) {
 
867
    if (!valid_advance(a)) {
838
868
      /* We check for recursive tech loops later,
839
869
       * in build_required_techs_helper. */
840
 
      if (!tech_exists(a->req[0])) {
841
 
        freelog(LOG_FATAL, "\"%s\" tech \"%s\": req1 leads to removed tech \"%s\".",
842
 
                filename,
843
 
                advance_rule_name(i),
844
 
                advance_rule_name(a->req[0]));
845
 
        exit(EXIT_FAILURE);
 
870
      if (!valid_advance(a->require[AR_ONE])) {
 
871
        ruleset_error(LOG_FATAL,
 
872
                      "\"%s\" tech \"%s\": req1 leads to removed tech.",
 
873
                      filename,
 
874
                      advance_rule_name(a));
846
875
      } 
847
 
      if (!tech_exists(a->req[1])) {
848
 
        freelog(LOG_FATAL, "\"%s\" tech \"%s\": req2 leads to removed tech \"%s\".",
849
 
                filename,
850
 
                advance_rule_name(i),
851
 
                advance_rule_name(a->req[1]));
852
 
        exit(EXIT_FAILURE);
 
876
      if (!valid_advance(a->require[AR_TWO])) {
 
877
        ruleset_error(LOG_FATAL,
 
878
                      "\"%s\" tech \"%s\": req2 leads to removed tech.",
 
879
                      filename,
 
880
                      advance_rule_name(a));
853
881
      }
854
882
    }
855
 
  } tech_type_iterate_end;
 
883
  } advance_iterate_end;
856
884
 
857
885
  free(sec);
858
886
  section_file_check_unused(file, filename);
866
894
{
867
895
  char **sec;
868
896
  int nval;
 
897
  int user_flags;
 
898
  char **flaglist;
 
899
  int i;
869
900
  const char *filename = secfile_filename(file);
870
901
 
871
902
  (void) section_file_lookup(file, "datafile.description");     /* unused */
872
903
 
 
904
  /* User unit flag names */
 
905
  flaglist = secfile_lookup_str_vec(file, &user_flags,
 
906
                                    "flags.names");
 
907
 
 
908
  if (user_flags > MAX_NUM_USER_UNIT_FLAGS) {
 
909
    ruleset_error(LOG_FATAL, "\"%s\": Too many user unit type flags!",
 
910
                  filename);
 
911
  }
 
912
 
 
913
  for (i = 0; i < user_flags; i++) {
 
914
    set_user_unit_flag_name(F_USER_FLAG_1 + i, flaglist[i]);
 
915
  }
 
916
  for (; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
 
917
    set_user_unit_flag_name(F_USER_FLAG_1 + i, NULL);
 
918
  }
 
919
  if (flaglist) {
 
920
    free(flaglist);
 
921
  }
 
922
 
 
923
  /* 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) {
 
927
    ruleset_error(LOG_FATAL, "\"%s\": No unit classes?!?", filename);
 
928
  }
 
929
  if(nval > UCL_LAST) {
 
930
    ruleset_error(LOG_FATAL, "\"%s\": Too many unit classes (%d, max %d)",
 
931
                  filename, nval, UCL_LAST);
 
932
  }
 
933
 
 
934
  game.control.num_unit_classes = nval;
 
935
 
 
936
  unit_class_iterate(punitclass) {
 
937
    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;
 
942
  } unit_class_iterate_end;
 
943
 
873
944
  /* The names: */
874
945
  sec = secfile_get_secnames_prefix(file, UNIT_SECTION_PREFIX, &nval);
875
946
  freelog(LOG_VERBOSE, "%d unit types (including possibly unused)", nval);
876
947
  if(nval == 0) {
877
 
    freelog(LOG_FATAL, "\"%s\": No units?!?", filename);
878
 
    exit(EXIT_FAILURE);
 
948
    ruleset_error(LOG_FATAL, "\"%s\": No unit types?!?", filename);
879
949
  }
880
950
  if(nval > U_LAST) {
881
 
    freelog(LOG_FATAL, "\"%s\": Too many units (%d, max %d)",
882
 
            filename, nval, U_LAST);
883
 
    exit(EXIT_FAILURE);
 
951
    ruleset_error(LOG_FATAL, "\"%s\": Too many unit types (%d, max %d)",
 
952
                  filename, nval, U_LAST);
884
953
  }
885
954
 
886
955
  game.control.num_unit_types = nval;
887
956
 
888
957
  unit_type_iterate(punittype) {
889
 
    const int i = punittype->index;
 
958
    const int i = utype_index(punittype);
890
959
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
891
960
 
892
961
    name_strlcpy(punittype->name.vernacular, name);
903
972
{
904
973
  struct unit_type *u;
905
974
  int i, j, ival, nval, vet_levels, vet_levels_default;
906
 
  char *sval, **slist, **sec;
 
975
  char *sval, **slist, **sec, **csec;
907
976
  const char *filename = secfile_filename(file);
908
977
  char **vnlist, **def_vnlist;
909
978
  int *vblist, *def_vblist;
915
984
   */
916
985
  sec = secfile_get_secnames_prefix(file, UNIT_SECTION_PREFIX, &nval);
917
986
 
918
 
#define CHECK_VETERAN_LIMIT                                             \
919
 
if (vet_levels_default > MAX_VET_LEVELS || vet_levels > MAX_VET_LEVELS) { \
920
 
  freelog(LOG_FATAL, "\"%s\": Too many veteran levels, %d is the maximum!", \
921
 
          filename, MAX_VET_LEVELS);                                    \
922
 
  exit(EXIT_FAILURE);                                                   \
 
987
#define CHECK_VETERAN_LIMIT(_count, _string)                            \
 
988
if (_count > MAX_VET_LEVELS) {                                          \
 
989
  ruleset_error(LOG_FATAL, "\"%s\": Too many " _string " entries (%d, max %d)", \
 
990
                filename, _count, MAX_VET_LEVELS);                      \
923
991
}
924
992
 
925
993
  /* level names */
926
994
  def_vnlist = secfile_lookup_str_vec(file, &vet_levels_default,
927
995
                                "veteran_system.veteran_names");
 
996
  CHECK_VETERAN_LIMIT(vet_levels_default, "veteran_names");
928
997
 
929
998
  unit_type_iterate(u) {
930
 
    const int i = u->index;
 
999
    const int i = utype_index(u);
931
1000
 
932
1001
    vnlist = secfile_lookup_str_vec(file, &vet_levels,
933
1002
                                    "%s.veteran_names", sec[i]);
934
 
    CHECK_VETERAN_LIMIT
 
1003
    CHECK_VETERAN_LIMIT(vet_levels, "veteran_names");
935
1004
    if (vnlist) {
936
1005
      /* unit has own veterancy settings */
937
1006
      for (j = 0; j < vet_levels; j++) {
955
1024
  /* power factor */
956
1025
  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
957
1026
                                      "veteran_system.veteran_power_fact");
 
1027
  CHECK_VETERAN_LIMIT(vet_levels_default, "veteran_power_fact");
958
1028
  unit_type_iterate(u) {
959
 
    const int i = u->index;
 
1029
    const int i = utype_index(u);
960
1030
 
961
1031
    vblist = secfile_lookup_int_vec(file, &vet_levels,
962
1032
                                    "%s.veteran_power_fact", sec[i]);
963
 
    CHECK_VETERAN_LIMIT
 
1033
    CHECK_VETERAN_LIMIT(vet_levels, "veteran_power_fact");
964
1034
    if (vblist) {
965
1035
      for (j = 0; j < vet_levels; j++) {
966
1036
        u->veteran[j].power_fact = ((double)vblist[j]) / 100;
979
1049
  /* raise chance */
980
1050
  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
981
1051
                                      "veteran_system.veteran_raise_chance");
982
 
  CHECK_VETERAN_LIMIT
 
1052
  CHECK_VETERAN_LIMIT(vet_levels_default, "veteran_raise_chance");
983
1053
  for (i = 0; i < vet_levels_default; i++) {
984
1054
    game.veteran_chance[i] = def_vblist[i];
985
1055
  }
993
1063
  /* work raise chance */
994
1064
  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
995
1065
                                    "veteran_system.veteran_work_raise_chance");
996
 
  CHECK_VETERAN_LIMIT
 
1066
  CHECK_VETERAN_LIMIT(vet_levels_default, "veteran_work_raise_chance");
997
1067
  for (i = 0; i < vet_levels_default; i++) {
998
1068
    game.work_veteran_chance[i] = def_vblist[i];
999
1069
  }
1004
1074
    free(def_vblist);
1005
1075
  }
1006
1076
 
1007
 
  /* highseas loss pct */
1008
 
  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
1009
 
                        "veteran_system.veteran_highseas_loss_pct");
1010
 
  for (i = 0; i < vet_levels_default; i++) {
1011
 
    game.trireme_loss_chance[i] = def_vblist[i];
1012
 
  }
1013
 
  for (; i < MAX_VET_LEVELS; i++) {
1014
 
    game.trireme_loss_chance[i] = 50; /* default */
1015
 
  }
1016
 
  if (def_vblist) {
1017
 
    free(def_vblist);
1018
 
  }
1019
 
  
1020
1077
  /* move bonus */
1021
1078
  def_vblist = secfile_lookup_int_vec(file, &vet_levels_default,
1022
1079
                                      "veteran_system.veteran_move_bonus");
 
1080
  CHECK_VETERAN_LIMIT(vet_levels_default, "veteran_move_bonus");
1023
1081
  unit_type_iterate(u) {
1024
 
    const int i = u->index;
 
1082
    const int i = utype_index(u);
1025
1083
 
1026
1084
    vblist = secfile_lookup_int_vec(file, &vet_levels,
1027
1085
                        "%s.veteran_move_bonus", sec[i]);
1028
 
    CHECK_VETERAN_LIMIT
 
1086
    CHECK_VETERAN_LIMIT(vet_levels, "veteran_move_bonus");
1029
1087
    if (vblist) {
1030
1088
      for (j = 0; j < vet_levels; j++) {
1031
1089
        u->veteran[j].move_bonus = vblist[j];
1041
1099
    free(def_vblist);
1042
1100
  }
1043
1101
 
 
1102
  csec = secfile_get_secnames_prefix(file, UNIT_CLASS_SECTION_PREFIX, &nval);
 
1103
 
 
1104
  unit_class_iterate(ut) {
 
1105
    int i = uclass_index(ut);
 
1106
    char tmp[200] = "\0";
 
1107
    char *hut_str;
 
1108
 
 
1109
    mystrlcat(tmp, csec[i], 200);
 
1110
    mystrlcat(tmp, ".move_type", 200);
 
1111
    ut->move_type = lookup_move_type(file, tmp, filename);
 
1112
    ut->min_speed = SINGLE_MOVE * secfile_lookup_int(file, "%s.min_speed", csec[i]);
 
1113
    ut->hp_loss_pct = secfile_lookup_int(file,"%s.hp_loss_pct", csec[i]);
 
1114
 
 
1115
    hut_str = secfile_lookup_str_default(file, "Normal", "%s.hut_behavior", csec[i]);
 
1116
    if (mystrcasecmp(hut_str, "Normal") == 0) {
 
1117
      ut->hut_behavior = HUT_NORMAL;
 
1118
    } else if (mystrcasecmp(hut_str, "Nothing") == 0) {
 
1119
      ut->hut_behavior = HUT_NOTHING;
 
1120
    } else if (mystrcasecmp(hut_str, "Frighten") == 0) {
 
1121
      ut->hut_behavior = HUT_FRIGHTEN;
 
1122
    } else {
 
1123
      ruleset_error(LOG_FATAL,
 
1124
                    "\"%s\" unit_class \"%s\":"
 
1125
                    " Illegal hut behavior \"%s\".",
 
1126
                    filename,
 
1127
                    uclass_rule_name(ut),
 
1128
                    hut_str);
 
1129
    }
 
1130
 
 
1131
    BV_CLR_ALL(ut->flags);
 
1132
    slist = secfile_lookup_str_vec(file, &nval, "%s.flags", csec[i]);
 
1133
    for(j = 0; j < nval; j++) {
 
1134
      sval = slist[j];
 
1135
      if(strcmp(sval,"") == 0) {
 
1136
        continue;
 
1137
      }
 
1138
      ival = find_unit_class_flag_by_rule_name(sval);
 
1139
      if (ival == UCF_LAST) {
 
1140
        freelog(LOG_ERROR, "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
 
1141
                filename,
 
1142
                uclass_rule_name(ut),
 
1143
                sval);
 
1144
        ival = find_unit_flag_by_rule_name(sval);
 
1145
        if (ival != F_LAST) {
 
1146
          freelog(LOG_ERROR, "\"%s\" unit_class \"%s\": unit_type flag!",
 
1147
                  filename,
 
1148
                  uclass_rule_name(ut));
 
1149
        }
 
1150
      } else if (ut->move_type == SEA_MOVING
 
1151
                 && ( ival == UCF_ROAD_NATIVE || ival == UCF_RIVER_NATIVE)) {
 
1152
        freelog(LOG_ERROR, "\"%s\" unit_class \"%s\": cannot give \"%s\" flag"
 
1153
                " to sea moving unit",
 
1154
                filename,
 
1155
                uclass_rule_name(ut),
 
1156
                sval);
 
1157
      } else {
 
1158
        BV_SET(ut->flags, ival);
 
1159
      }
 
1160
    }
 
1161
    free(slist);
 
1162
 
 
1163
  } unit_class_iterate_end;
 
1164
 
1044
1165
  /* Tech and Gov requirements */  
1045
1166
  unit_type_iterate(u) {
1046
 
    const int i = u->index;
 
1167
    const int i = utype_index(u);
1047
1168
 
1048
 
    u->tech_requirement = lookup_tech(file, sec[i], "tech_req", TRUE,
1049
 
                                      filename, u->name.vernacular);
 
1169
    u->require_advance = lookup_tech(file, sec[i], "tech_req", LOG_FATAL,
 
1170
                                     filename, u->name.vernacular);
1050
1171
    if (section_file_lookup(file, "%s.gov_req", sec[i])) {
1051
1172
      char tmp[200] = "\0";
1052
1173
      mystrlcat(tmp, sec[i], 200);
1053
1174
      mystrlcat(tmp, ".gov_req", 200);
1054
 
      u->gov_requirement = lookup_government(file, tmp, filename);
 
1175
      u->need_government = lookup_government(file, tmp, filename);
1055
1176
    } else {
1056
 
      u->gov_requirement = NULL; /* no requirement */
 
1177
      u->need_government = NULL; /* no requirement */
1057
1178
    }
1058
1179
  } unit_type_iterate_end;
1059
1180
  
1060
1181
  unit_type_iterate(u) {
1061
 
    const int i = u->index;
 
1182
    const int i = utype_index(u);
1062
1183
 
1063
 
    u->obsoleted_by = lookup_unit_type(file, sec[i], "obsolete_by", FALSE,
 
1184
    u->obsoleted_by = lookup_unit_type(file, sec[i], "obsolete_by", LOG_ERROR,
1064
1185
                                       filename, u->name.vernacular);
1065
1186
  } unit_type_iterate_end;
1066
1187
 
1067
1188
  /* main stats: */
1068
1189
  unit_type_iterate(u) {
1069
 
    const int i = u->index;
 
1190
    const int i = utype_index(u);
1070
1191
    struct unit_class *pclass;
1071
1192
 
1072
 
    u->impr_requirement = lookup_building(file, sec[i], "impr_req", FALSE,
 
1193
    u->need_improvement = lookup_building(file, sec[i], "impr_req", LOG_ERROR,
1073
1194
                                          filename, u->name.vernacular);
1074
1195
 
1075
1196
    sval = secfile_lookup_str(file, "%s.class", sec[i]);
1076
1197
    pclass = find_unit_class_by_rule_name(sval);
1077
1198
    if (!pclass) {
1078
 
      freelog(LOG_FATAL, "\"%s\" unit_type \"%s\": bad class \"%s\".",
1079
 
              filename,
1080
 
              utype_rule_name(u),
1081
 
              sval);
1082
 
      exit(EXIT_FAILURE);
 
1199
      ruleset_error(LOG_FATAL,
 
1200
                    "\"%s\" unit_type \"%s\":"
 
1201
                    " bad class \"%s\".",
 
1202
                    filename,
 
1203
                    utype_rule_name(u),
 
1204
                    sval);
1083
1205
    }
1084
1206
    u->uclass = pclass;
1085
 
    switch (pclass->id)
1086
 
    {
1087
 
    case UCL_MISSILE:
1088
 
    case UCL_NUCLEAR:
1089
 
      u->move_type = AIR_MOVING;
1090
 
      break;
1091
 
    default:
1092
 
      u->move_type = pclass->id;
1093
 
      break;
1094
 
    }
1095
1207
    
1096
1208
    sz_strlcpy(u->sound_move,
1097
1209
               secfile_lookup_str_default(file, "-", "%s.sound_move",
1129
1241
    u->hp = secfile_lookup_int(file,"%s.hitpoints", sec[i]);
1130
1242
    u->firepower = secfile_lookup_int(file,"%s.firepower", sec[i]);
1131
1243
    if (u->firepower <= 0) {
1132
 
      freelog(LOG_FATAL, "\"%s\" unit_type \"%s\":"
1133
 
                         " firepower is %d,"
1134
 
                         " but must be at least 1. "
1135
 
                         "  If you want no attack ability,"
1136
 
                         " set the unit's attack strength to 0.",
1137
 
              filename,
1138
 
              utype_rule_name(u),
1139
 
              u->firepower);
1140
 
      exit(EXIT_FAILURE);
 
1244
      ruleset_error(LOG_FATAL,
 
1245
                    "\"%s\" unit_type \"%s\":"
 
1246
                    " firepower is %d,"
 
1247
                    " but must be at least 1. "
 
1248
                    "  If you want no attack ability,"
 
1249
                    " set the unit's attack strength to 0.",
 
1250
                    filename,
 
1251
                    utype_rule_name(u),
 
1252
                    u->firepower);
1141
1253
    }
1142
1254
    u->fuel = secfile_lookup_int(file,"%s.fuel", sec[i]);
1143
1255
 
1147
1259
                                                get_output_identifier(o));
1148
1260
    } output_type_iterate_end;
1149
1261
 
 
1262
    slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec[i]);
 
1263
    BV_CLR_ALL(u->cargo);
 
1264
    for (j = 0; j < nval; j++) {
 
1265
      struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
 
1266
 
 
1267
      if (!class) {
 
1268
        ruleset_error(LOG_FATAL,
 
1269
                      "\"%s\" unit_type \"%s\":"
 
1270
                      "has unknown unit class %s as cargo.",
 
1271
                      filename,
 
1272
                      utype_rule_name(u),
 
1273
                      slist[j]);
 
1274
      }
 
1275
 
 
1276
      BV_SET(u->cargo, uclass_index(class));
 
1277
    }
 
1278
    free(slist);
 
1279
 
 
1280
    slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec[i]);
 
1281
    BV_CLR_ALL(u->targets);
 
1282
    for (j = 0; j < nval; j++) {
 
1283
      struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
 
1284
 
 
1285
      if (!class) {
 
1286
        ruleset_error(LOG_FATAL,
 
1287
                      "\"%s\" unit_type \"%s\":"
 
1288
                      "has unknown unit class %s as target.",
 
1289
                      filename,
 
1290
                      utype_rule_name(u),
 
1291
                      slist[j]);
 
1292
      }
 
1293
 
 
1294
      BV_SET(u->targets, uclass_index(class));
 
1295
    }
 
1296
    free(slist);
 
1297
 
 
1298
    /* Set also all classes that are never unreachable as targets. */
 
1299
    unit_class_iterate(pclass) {
 
1300
      if (!uclass_has_flag(pclass, UCF_UNREACHABLE)) {
 
1301
        BV_SET(u->targets, uclass_index(pclass));
 
1302
      }
 
1303
    } unit_class_iterate_end;
 
1304
 
1150
1305
    u->helptext = lookup_helptext(file, sec[i]);
1151
1306
 
1152
1307
    u->paratroopers_range = secfile_lookup_int_default(file,
1157
1312
        0, "%s.paratroopers_mr_sub", sec[i]);
1158
1313
    u->bombard_rate = secfile_lookup_int_default(file,
1159
1314
        0, "%s.bombard_rate", sec[i]);
 
1315
    u->city_size = secfile_lookup_int_default(file, 1, "%s.city_size", sec[i]);
1160
1316
  } unit_type_iterate_end;
1161
1317
  
1162
1318
  /* flags */
1163
1319
  unit_type_iterate(u) {
1164
 
    const int i = u->index;
 
1320
    const int i = utype_index(u);
1165
1321
 
1166
1322
    BV_CLR_ALL(u->flags);
1167
1323
    assert(!utype_has_flag(u, F_LAST-1));
1178
1334
                filename,
1179
1335
                utype_rule_name(u),
1180
1336
                sval);
 
1337
        ival = find_unit_class_flag_by_rule_name(sval);
 
1338
        if (ival != UCF_LAST) {
 
1339
          freelog(LOG_ERROR, "\"%s\" unit_type \"%s\": unit_class flag!",
 
1340
                  filename,
 
1341
                  utype_rule_name(u));
 
1342
        }
 
1343
      } else {
 
1344
        BV_SET(u->flags, ival);
1181
1345
      }
1182
 
      BV_SET(u->flags, ival);
1183
1346
      assert(utype_has_flag(u, ival));
1184
1347
    }
1185
1348
    free(slist);
1187
1350
    
1188
1351
  /* roles */
1189
1352
  unit_type_iterate(u) {
1190
 
    const int i = u->index;
 
1353
    const int i = utype_index(u);
1191
1354
 
1192
1355
    BV_CLR_ALL(u->roles);
1193
1356
    
1200
1363
      ival = find_unit_role_by_rule_name(sval);
1201
1364
      if (ival==L_LAST) {
1202
1365
        freelog(LOG_ERROR, "\"%s\" unit_type \"%s\": bad role name \"%s\".",
1203
 
                filename,
1204
 
                utype_rule_name(u),
1205
 
                sval);
 
1366
                filename, utype_rule_name(u), sval);
 
1367
      } else if ((ival == L_FERRYBOAT || ival == L_BARBARIAN_BOAT)
 
1368
                 && u->uclass->move_type == LAND_MOVING) {
 
1369
        freelog(LOG_ERROR,
 
1370
                "\"%s\" unit_type \"%s\": role \"%s\" for land moving unit.",
 
1371
                filename, utype_rule_name(u), sval);
 
1372
      } else {
 
1373
        BV_SET(u->roles, ival - L_FIRST);
1206
1374
      }
1207
 
      BV_SET(u->roles, ival - L_FIRST);
1208
1375
      assert(utype_has_role(u, ival));
1209
1376
    }
1210
1377
    free(slist);
1212
1379
 
1213
1380
  /* Some more consistency checking: */
1214
1381
  unit_type_iterate(u) {
1215
 
    if (!tech_exists(u->tech_requirement)) {
 
1382
    if (!valid_advance(u->require_advance)) {
1216
1383
      freelog(LOG_ERROR,
1217
1384
              "\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
1218
1385
              filename,
1219
1386
              utype_rule_name(u),
1220
 
              advance_rule_name(u->tech_requirement));
1221
 
      u->tech_requirement = A_LAST;
 
1387
              advance_rule_name(u->require_advance));
 
1388
      u->require_advance = A_NEVER;
 
1389
    }
 
1390
 
 
1391
    if (utype_has_flag(u, F_SETTLERS)
 
1392
        && u->city_size <= 0) {
 
1393
      ruleset_error(LOG_ERROR, "\"%s\": Unit %s would build size %d cities",
 
1394
                    filename, utype_rule_name(u), u->city_size);
 
1395
      u->city_size = 1;
1222
1396
    }
1223
1397
  } unit_type_iterate_end;
1224
1398
 
1227
1401
     
1228
1402
  /* Check some required flags and roles etc: */
1229
1403
  if(num_role_units(F_CITIES)==0) {
1230
 
    freelog(LOG_FATAL, "\"%s\": No flag=cities units?", filename);
1231
 
    exit(EXIT_FAILURE);
 
1404
    ruleset_error(LOG_FATAL, "\"%s\": No flag=cities units?", filename);
1232
1405
  }
1233
1406
  if(num_role_units(F_SETTLERS)==0) {
1234
 
    freelog(LOG_FATAL, "\"%s\": No flag=settler units?", filename);
1235
 
    exit(EXIT_FAILURE);
 
1407
    ruleset_error(LOG_FATAL, "\"%s\": No flag=settler units?", filename);
1236
1408
  }
1237
1409
  if(num_role_units(L_EXPLORER)==0) {
1238
 
    freelog(LOG_FATAL, "\"%s\": No role=explorer units?", filename);
1239
 
    exit(EXIT_FAILURE);
 
1410
    ruleset_error(LOG_FATAL, "\"%s\": No role=explorer units?", filename);
1240
1411
  }
1241
1412
  if(num_role_units(L_FERRYBOAT)==0) {
1242
 
    freelog(LOG_FATAL, "\"%s\": No role=ferryboat units?", filename);
1243
 
    exit(EXIT_FAILURE);
 
1413
    ruleset_error(LOG_FATAL, "\"%s\": No role=ferryboat units?", filename);
1244
1414
  }
1245
1415
  if(num_role_units(L_FIRSTBUILD)==0) {
1246
 
    freelog(LOG_FATAL, "\"%s\": No role=firstbuild units?", filename);
1247
 
    exit(EXIT_FAILURE);
 
1416
    ruleset_error(LOG_FATAL, "\"%s\": No role=firstbuild units?", filename);
1248
1417
  }
1249
1418
  if (num_role_units(L_BARBARIAN) == 0 && game.info.barbarianrate > 0) {
1250
 
    freelog(LOG_FATAL, "\"%s\": No role=barbarian units?", filename);
1251
 
    exit(EXIT_FAILURE);
 
1419
    ruleset_error(LOG_FATAL, "\"%s\": No role=barbarian units?", filename);
1252
1420
  }
1253
1421
  if (num_role_units(L_BARBARIAN_LEADER) == 0 && game.info.barbarianrate > 0) {
1254
 
    freelog(LOG_FATAL, "\"%s\": No role=barbarian leader units?", filename);
1255
 
    exit(EXIT_FAILURE);
 
1422
    ruleset_error(LOG_FATAL, "\"%s\": No role=barbarian leader units?", filename);
1256
1423
  }
1257
1424
  if (num_role_units(L_BARBARIAN_BUILD) == 0 && game.info.barbarianrate > 0) {
1258
 
    freelog(LOG_FATAL, "\"%s\": No role=barbarian build units?", filename);
1259
 
    exit(EXIT_FAILURE);
 
1425
    ruleset_error(LOG_FATAL, "\"%s\": No role=barbarian build units?", filename);
1260
1426
  }
1261
1427
  if (num_role_units(L_BARBARIAN_BOAT) == 0 && game.info.barbarianrate > 0) {
1262
 
    freelog(LOG_FATAL, "\"%s\": No role=barbarian ship units?", filename);
1263
 
    exit(EXIT_FAILURE);
 
1428
    ruleset_error(LOG_FATAL, "\"%s\": No role=barbarian ship units?", filename);
1264
1429
  } else if (num_role_units(L_BARBARIAN_BOAT) > 0) {
1265
1430
    u = get_role_unit(L_BARBARIAN_BOAT,0);
1266
 
    if(u->move_type != SEA_MOVING) {
1267
 
      freelog(LOG_FATAL, "\"%s\": Barbarian boat (%s) needs to be a sea unit.",
1268
 
              filename,
1269
 
              utype_rule_name(u));
1270
 
      exit(EXIT_FAILURE);
 
1431
    if(utype_move_type(u) != SEA_MOVING) {
 
1432
      ruleset_error(LOG_FATAL,
 
1433
                    "\"%s\": Barbarian boat (%s) needs to be a sea unit.",
 
1434
                    filename,
 
1435
                    utype_rule_name(u));
1271
1436
    }
1272
1437
  }
1273
1438
  if (num_role_units(L_BARBARIAN_SEA) == 0 && game.info.barbarianrate > 0) {
1274
 
    freelog(LOG_FATAL, "\"%s\": No role=sea raider barbarian units?", filename);
1275
 
    exit(EXIT_FAILURE);
 
1439
    ruleset_error(LOG_FATAL, "\"%s\": No role=sea raider barbarian units?",
 
1440
                  filename);
1276
1441
  }
1277
1442
 
1278
1443
  update_simple_ai_types();
1279
1444
 
 
1445
  free(csec);
1280
1446
  free(sec);
1281
1447
  section_file_check_unused(file, filename);
1282
1448
  section_file_free(file);
1288
1454
static void load_building_names(struct section_file *file)
1289
1455
{
1290
1456
  char **sec;
1291
 
  int nval;
 
1457
  int i, nval;
1292
1458
  const char *filename = secfile_filename(file);
1293
1459
 
1294
1460
  (void) section_file_lookup(file, "datafile.description");     /* unused */
1297
1463
  sec = secfile_get_secnames_prefix(file, BUILDING_SECTION_PREFIX, &nval);
1298
1464
  freelog(LOG_VERBOSE, "%d improvement types (including possibly unused)", nval);
1299
1465
  if (nval == 0) {
1300
 
    freelog(LOG_FATAL, "\"%s\": No improvements?!?", filename);
1301
 
    exit(EXIT_FAILURE);
 
1466
    ruleset_error(LOG_FATAL, "\"%s\": No improvements?!?", filename);
1302
1467
  }
1303
1468
  if (nval > B_LAST) {
1304
 
    freelog(LOG_FATAL, "\"%s\": Too many improvements (%d, max %d)",
1305
 
            filename, nval, B_LAST);
1306
 
    exit(EXIT_FAILURE);
 
1469
    ruleset_error(LOG_FATAL, "\"%s\": Too many improvements (%d, max %d)",
 
1470
                  filename, nval, B_LAST);
1307
1471
  }
1308
1472
 
1309
1473
  game.control.num_impr_types = nval;
1310
1474
 
1311
 
  impr_type_iterate(i) {
 
1475
  for (i = 0; i < nval; i++) {
1312
1476
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
1313
1477
    struct impr_type *b = improvement_by_number(i);
1314
1478
 
1315
1479
    name_strlcpy(b->name.vernacular, name);
1316
1480
    b->name.translated = NULL;
1317
 
  } impr_type_iterate_end;
1318
 
 
1319
 
  ruleset_cache_init();
 
1481
  }
1320
1482
 
1321
1483
  free(sec);
1322
1484
}
1338
1500
    struct impr_type *b = improvement_by_number(i);
1339
1501
    struct requirement_vector *reqs =
1340
1502
      lookup_req_list(file, sec[i], "reqs",
1341
 
                      improvement_rule_name(i));
 
1503
                      improvement_rule_name(b));
1342
1504
    char *sval, **slist;
1343
1505
    int j, nflags, ival;
1344
1506
 
1345
1507
    item = secfile_lookup_str(file, "%s.genus", sec[i]);
1346
1508
    b->genus = find_genus_by_rule_name(item);
1347
1509
    if (b->genus == IG_LAST) {
1348
 
      freelog(LOG_FATAL,
1349
 
              "\"%s\" improvement \"%s\": couldn't match genus \"%s\".",
1350
 
              filename,
1351
 
              improvement_rule_name(i),
1352
 
              item);
1353
 
      exit(EXIT_FAILURE);
 
1510
      ruleset_error(LOG_FATAL,
 
1511
                    "\"%s\" improvement \"%s\": couldn't match genus \"%s\".",
 
1512
                    filename,
 
1513
                    improvement_rule_name(b),
 
1514
                    item);
1354
1515
    }
1355
1516
 
1356
1517
    slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec[i]);
1366
1527
        freelog(LOG_ERROR,
1367
1528
                "\"%s\" improvement \"%s\": bad flag name \"%s\".",
1368
1529
                filename,
1369
 
                improvement_rule_name(i),
 
1530
                improvement_rule_name(b),
1370
1531
                sval);
 
1532
      } else {
 
1533
        b->flags |= (1<<ival);
1371
1534
      }
1372
 
      b->flags |= (1<<ival);
1373
1535
    }
1374
1536
    free(slist);
1375
1537
 
1376
1538
    requirement_vector_copy(&b->reqs, reqs);
1377
1539
 
1378
 
    b->obsolete_by = lookup_tech(file, sec[i], "obsolete_by", FALSE,
 
1540
    b->obsolete_by = lookup_tech(file, sec[i], "obsolete_by", LOG_ERROR,
1379
1541
                                 filename, b->name.vernacular);
1380
 
    if (b->obsolete_by == A_NONE || !tech_exists(b->obsolete_by)) {
 
1542
    if (advance_by_number(A_NONE) == b->obsolete_by) {
1381
1543
      /* 
1382
1544
       * The ruleset can specify "None" for a never-obsoleted
1383
1545
       * improvement.  Currently this means A_NONE, which is an
1384
 
       * unnecessary special-case.  We use A_LAST to flag a
 
1546
       * unnecessary special-case.  We use A_NEVER to flag a
1385
1547
       * never-obsoleted improvement in the code instead.
 
1548
       * (Test for valid_advance() later.)
1386
1549
       */
1387
 
      b->obsolete_by = A_LAST;
 
1550
      b->obsolete_by = A_NEVER;
1388
1551
    }
1389
1552
 
1390
 
    b->replaced_by = lookup_impr_type(file, sec[i], "replaced_by", FALSE,
1391
 
                                      filename, b->name.vernacular);
 
1553
    b->replaced_by = lookup_building(file, sec[i], "replaced_by", LOG_ERROR,
 
1554
                                     filename, b->name.vernacular);
1392
1555
 
1393
1556
    b->build_cost = secfile_lookup_int(file, "%s.build_cost", sec[i]);
1394
1557
 
1410
1573
 
1411
1574
    b->allows_units = FALSE;
1412
1575
    unit_type_iterate(ut) {
1413
 
      if (ut->impr_requirement == i) {
 
1576
      if (ut->need_improvement == b) {
1414
1577
        b->allows_units = TRUE;
1415
1578
        break;
1416
1579
      }
1418
1581
  }
1419
1582
 
1420
1583
  /* Some more consistency checking: */
1421
 
  impr_type_iterate(i) {
1422
 
    struct impr_type *b = improvement_by_number(i);
1423
 
 
1424
 
    if (improvement_exists(i)) {
1425
 
      if (b->obsolete_by != A_LAST
1426
 
          && (b->obsolete_by == A_NONE || !tech_exists(b->obsolete_by))) {
 
1584
  improvement_iterate(b) {
 
1585
    if (valid_improvement(b)) {
 
1586
      if (A_NEVER != b->obsolete_by
 
1587
          && !valid_advance(b->obsolete_by)) {
1427
1588
        freelog(LOG_ERROR,
1428
1589
                "\"%s\" improvement \"%s\": obsoleted by removed tech \"%s\".",
1429
1590
                filename,
1430
 
                improvement_rule_name(i),
 
1591
                improvement_rule_name(b),
1431
1592
                advance_rule_name(b->obsolete_by));
1432
 
        b->obsolete_by = A_LAST;
 
1593
        b->obsolete_by = A_NEVER;
1433
1594
      }
1434
1595
    }
1435
 
  } impr_type_iterate_end;
 
1596
  } improvement_iterate_end;
1436
1597
 
1437
1598
  free(sec);
1438
1599
  section_file_check_unused(file, filename);
1442
1603
/**************************************************************************
1443
1604
  ...  
1444
1605
**************************************************************************/
1445
 
static void load_names(struct section_file *file)
 
1606
static void load_terrain_names(struct section_file *file)
1446
1607
{
1447
1608
  int nval;
1448
1609
  char **sec;
1454
1615
 
1455
1616
  sec = secfile_get_secnames_prefix(file, TERRAIN_SECTION_PREFIX, &nval);
1456
1617
  if (nval == 0) {
1457
 
    freelog(LOG_FATAL, "\"%s\": ruleset doesn't have any terrains.",
1458
 
            filename);
1459
 
    exit(EXIT_FAILURE);
 
1618
    ruleset_error(LOG_FATAL, "\"%s\": ruleset doesn't have any terrains.",
 
1619
                  filename);
 
1620
  }
 
1621
  if (nval > MAX_NUM_TERRAINS) {
 
1622
    ruleset_error(LOG_FATAL, "\"%s\": Too many terrains (%d, max %d)",
 
1623
                  filename,
 
1624
                  nval,
 
1625
                  MAX_NUM_TERRAINS);
1460
1626
  }
1461
1627
  game.control.terrain_count = nval;
1462
1628
 
 
1629
  /* avoid re-reading files */
 
1630
  if (terrain_sections) {
 
1631
    free(terrain_sections);
 
1632
  }
 
1633
  terrain_sections = fc_calloc(nval, MAX_SECTION_LABEL);
 
1634
 
1463
1635
  terrain_type_iterate(pterrain) {
1464
 
    char *name = secfile_lookup_str(file, "%s.name",
1465
 
                                    sec[pterrain->index]);
 
1636
    const int i = terrain_index(pterrain);
 
1637
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
1466
1638
 
1467
1639
    name_strlcpy(pterrain->name.vernacular, name);
1468
1640
    if (0 == strcmp(pterrain->name.vernacular, "unused")) {
1469
1641
      pterrain->name.vernacular[0] = '\0';
1470
1642
    }
1471
1643
    pterrain->name.translated = NULL;
 
1644
 
 
1645
    section_strlcpy(&terrain_sections[i * MAX_SECTION_LABEL], sec[i]);
1472
1646
  } terrain_type_iterate_end;
1473
1647
 
1474
1648
  free(sec);
1475
1649
 
 
1650
  /* resource names */
 
1651
 
1476
1652
  sec = secfile_get_secnames_prefix(file, RESOURCE_SECTION_PREFIX, &nval);
 
1653
  if (nval > MAX_NUM_RESOURCES) {
 
1654
    ruleset_error(LOG_FATAL, "\"%s\": Too many resources (%d, max %d)",
 
1655
                  filename,
 
1656
                  nval,
 
1657
                  MAX_NUM_RESOURCES);
 
1658
  }
1477
1659
  game.control.resource_count = nval;
1478
1660
 
 
1661
  /* avoid re-reading files */
 
1662
  if (resource_sections) {
 
1663
    free(resource_sections);
 
1664
  }
 
1665
  resource_sections = fc_calloc(nval, MAX_SECTION_LABEL);
 
1666
 
1479
1667
  resource_type_iterate(presource) {
1480
 
    char *name = secfile_lookup_str(file, "%s.name",
1481
 
                                    sec[presource->index]);
 
1668
    const int i = resource_index(presource);
 
1669
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
1482
1670
 
1483
1671
    name_strlcpy(presource->name.vernacular, name);
1484
1672
    if (0 == strcmp(presource->name.vernacular, "unused")) {
1485
1673
      presource->name.vernacular[0] = '\0';
1486
1674
    }
1487
1675
    presource->name.translated = NULL;
 
1676
 
 
1677
    section_strlcpy(&resource_sections[i * MAX_SECTION_LABEL], sec[i]);
1488
1678
  } resource_type_iterate_end;
1489
1679
 
1490
1680
  free(sec);
1491
1681
 
 
1682
  /* base names */
 
1683
 
 
1684
  sec = secfile_get_secnames_prefix(file, BASE_SECTION_PREFIX, &nval);
 
1685
  if (nval > MAX_BASE_TYPES) {
 
1686
    ruleset_error(LOG_FATAL, "\"%s\": Too many base types (%d, max %d)",
 
1687
                  filename,
 
1688
                  nval,
 
1689
                  MAX_BASE_TYPES);
 
1690
  }
 
1691
  game.control.num_base_types = nval;
 
1692
 
 
1693
  if (base_sections) {
 
1694
    free(base_sections);
 
1695
  }
 
1696
  base_sections = fc_calloc(nval, MAX_SECTION_LABEL);
 
1697
 
 
1698
  base_type_iterate(pbase) {
 
1699
    const int i = base_index(pbase);
 
1700
    char *name = secfile_lookup_str(file, "%s.name", sec[i]);
 
1701
 
 
1702
    name_strlcpy(pbase->name.vernacular, name);
 
1703
    pbase->name.translated = NULL;
 
1704
 
 
1705
    section_strlcpy(&base_sections[i * MAX_SECTION_LABEL], sec[i]);
 
1706
  } base_type_iterate_end;
 
1707
 
 
1708
  free(sec);
1492
1709
}
1493
1710
 
1494
1711
/**************************************************************************
1496
1713
**************************************************************************/
1497
1714
static void load_ruleset_terrain(struct section_file *file)
1498
1715
{
1499
 
  char *datafile_options;
1500
1716
  int nval;
1501
 
  char **tsec, **rsec, **res;
1502
1717
  int j;
 
1718
  char **res;
1503
1719
  const char *filename = secfile_filename(file);
1504
 
 
1505
 
  datafile_options =
1506
 
    check_ruleset_capabilities(file, "+1.9", filename);
 
1720
  /* char *datafile_options = */ (void)
 
1721
    check_ruleset_capabilities(file, TERRAIN_CAPABILITY, filename);
1507
1722
 
1508
1723
  /* options */
1509
1724
  terrain_control.may_road =
1518
1733
  /* parameters */
1519
1734
 
1520
1735
  terrain_control.ocean_reclaim_requirement_pct
1521
 
    = secfile_lookup_int_default(file, 9,
1522
 
                                 "parameters.ocean_reclaim_requirement_pct");
 
1736
    = secfile_lookup_int_default(file, 101,
 
1737
                                 "parameters.ocean_reclaim_requirement");
1523
1738
  terrain_control.land_channel_requirement_pct
1524
 
    = secfile_lookup_int_default(file, 9,
1525
 
                                 "parameters.land_channel_requirement_pct");
 
1739
    = secfile_lookup_int_default(file, 101,
 
1740
                                 "parameters.land_channel_requirement");
 
1741
  terrain_control.lake_max_size
 
1742
    = secfile_lookup_int_default(file, 0,
 
1743
                                 "parameters.lake_max_size");
 
1744
  map.server.ocean_resources
 
1745
    = secfile_lookup_bool_default(file, FALSE,
 
1746
                                  "parameters.ocean_resources");
1526
1747
  terrain_control.river_move_mode =
1527
1748
    secfile_lookup_int_default(file, RMV_FAST_STRICT, "parameters.river_move_mode");
1528
1749
  terrain_control.river_defense_bonus =
1534
1755
      "parameters.river_help_text");
1535
1756
    sz_strlcpy(terrain_control.river_help_text, s);
1536
1757
  }
1537
 
  terrain_control.fortress_defense_bonus =
1538
 
    secfile_lookup_int_default(file, 100, "parameters.fortress_defense_bonus");
1539
1758
 
1540
1759
  terrain_control.road_superhighway_trade_bonus =
1541
1760
    secfile_lookup_int_default(file, 50, "parameters.road_superhighway_trade_bonus");
1553
1772
                                   get_output_identifier(o));
1554
1773
  } output_type_iterate_end;
1555
1774
 
1556
 
  tsec = secfile_get_secnames_prefix(file, TERRAIN_SECTION_PREFIX, &nval);
1557
 
 
1558
1775
  /* terrain details */
1559
1776
 
1560
1777
  terrain_type_iterate(pterrain) {
1561
1778
    char **slist;
1562
 
    const int i = pterrain->index;
 
1779
    const int i = terrain_index(pterrain);
 
1780
    const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
1563
1781
 
1564
1782
    sz_strlcpy(pterrain->graphic_str,
1565
 
               secfile_lookup_str(file,"%s.graphic", tsec[i]));
 
1783
               secfile_lookup_str(file,"%s.graphic", tsection));
1566
1784
    sz_strlcpy(pterrain->graphic_alt,
1567
 
               secfile_lookup_str(file,"%s.graphic_alt", tsec[i]));
 
1785
               secfile_lookup_str(file,"%s.graphic_alt", tsection));
1568
1786
 
1569
1787
    pterrain->identifier
1570
 
      = secfile_lookup_str(file, "%s.identifier", tsec[i])[0];
 
1788
      = secfile_lookup_str(file, "%s.identifier", tsection)[0];
1571
1789
    if ('\0' == pterrain->identifier) {
1572
 
      freelog(LOG_FATAL, "\"%s\" [%s] missing identifier.",
1573
 
              filename, tsec[i]);
1574
 
      exit(EXIT_FAILURE);
 
1790
      ruleset_error(LOG_FATAL, "\"%s\" [%s] identifier missing value.",
 
1791
                    filename, tsection);
1575
1792
    }
1576
 
    if (UNKNOWN_TERRAIN_IDENTIFIER == pterrain->identifier) {
1577
 
      freelog(LOG_FATAL, "\"%s\" [%s] cannot use '%c' as an identifier;"
1578
 
                         " it is reserved.",
1579
 
              filename, tsec[i], pterrain->identifier);
1580
 
      exit(EXIT_FAILURE);
 
1793
    if (TERRAIN_UNKNOWN_IDENTIFIER == pterrain->identifier) {
 
1794
      ruleset_error(LOG_FATAL,
 
1795
                    "\"%s\" [%s] cannot use '%c' as an identifier;"
 
1796
                    " it is reserved for unknown terrain.",
 
1797
                    filename, tsection, pterrain->identifier);
1581
1798
    }
1582
1799
    for (j = T_FIRST; j < i; j++) {
1583
1800
      if (pterrain->identifier == terrain_by_number(j)->identifier) {
1584
 
        freelog(LOG_FATAL, "\"%s\" [%s] has the same identifier as \"%s\".",
1585
 
                filename,
1586
 
                tsec[i],
1587
 
                terrain_rule_name(terrain_by_number(j)));
1588
 
        exit(EXIT_FAILURE);
 
1801
        ruleset_error(LOG_FATAL,
 
1802
                      "\"%s\" [%s] has the same identifier as [%s].",
 
1803
                      filename,
 
1804
                      tsection,
 
1805
                      &terrain_sections[j * MAX_SECTION_LABEL]);
1589
1806
      }
1590
1807
    }
1591
1808
 
1592
1809
    pterrain->movement_cost
1593
 
      = secfile_lookup_int(file, "%s.movement_cost", tsec[i]);
 
1810
      = secfile_lookup_int(file, "%s.movement_cost", tsection);
1594
1811
    pterrain->defense_bonus
1595
 
      = secfile_lookup_int(file, "%s.defense_bonus", tsec[i]);
 
1812
      = secfile_lookup_int(file, "%s.defense_bonus", tsection);
1596
1813
 
1597
1814
    output_type_iterate(o) {
1598
1815
      pterrain->output[o]
1599
 
        = secfile_lookup_int_default(file, 0, "%s.%s", tsec[i],
 
1816
        = secfile_lookup_int_default(file, 0, "%s.%s", tsection,
1600
1817
                                     get_output_identifier(o));
1601
1818
    } output_type_iterate_end;
1602
1819
 
1603
 
    res = secfile_lookup_str_vec (file, &nval, "%s.resources", tsec[i]);
 
1820
    res = secfile_lookup_str_vec(file, &nval, "%s.resources", tsection);
1604
1821
    pterrain->resources = fc_calloc(nval + 1, sizeof(*pterrain->resources));
1605
1822
    for (j = 0; j < nval; j++) {
1606
 
      pterrain->resources[j] = find_resource_by_rule_name(res[j]);
1607
 
      if (!pterrain->resources[j]) {
1608
 
        freelog(LOG_FATAL, "\"%s\" [%s] could not find resource \"%s\".",
1609
 
                filename, tsec[i], res[j]);
1610
 
        exit(EXIT_FAILURE);
1611
 
      }
 
1823
      pterrain->resources[j] = lookup_resource(filename, res[j], tsection);
1612
1824
    }
1613
1825
    pterrain->resources[nval] = NULL;
1614
1826
    free(res);
1615
1827
    res = NULL;
1616
1828
 
1617
1829
    pterrain->road_trade_incr
1618
 
      = secfile_lookup_int(file, "%s.road_trade_incr", tsec[i]);
1619
 
    pterrain->road_time = secfile_lookup_int(file, "%s.road_time", tsec[i]);
 
1830
      = secfile_lookup_int(file, "%s.road_trade_incr", tsection);
 
1831
    pterrain->road_time = secfile_lookup_int(file, "%s.road_time", tsection);
1620
1832
 
1621
1833
    pterrain->irrigation_result
1622
 
      = lookup_terrain(secfile_lookup_str(file, "%s.irrigation_result",
1623
 
                                          tsec[i]), pterrain);
 
1834
      = lookup_terrain(file, "irrigation_result", pterrain);
1624
1835
    pterrain->irrigation_food_incr
1625
 
      = secfile_lookup_int(file, "%s.irrigation_food_incr", tsec[i]);
 
1836
      = secfile_lookup_int(file, "%s.irrigation_food_incr", tsection);
1626
1837
    pterrain->irrigation_time
1627
 
      = secfile_lookup_int(file, "%s.irrigation_time", tsec[i]);
 
1838
      = secfile_lookup_int(file, "%s.irrigation_time", tsection);
1628
1839
 
1629
1840
    pterrain->mining_result
1630
 
      = lookup_terrain(secfile_lookup_str(file, "%s.mining_result",
1631
 
                                          tsec[i]), pterrain);
 
1841
      = lookup_terrain(file, "mining_result", pterrain);
1632
1842
    pterrain->mining_shield_incr
1633
 
      = secfile_lookup_int(file, "%s.mining_shield_incr", tsec[i]);
 
1843
      = secfile_lookup_int(file, "%s.mining_shield_incr", tsection);
1634
1844
    pterrain->mining_time
1635
 
      = secfile_lookup_int(file, "%s.mining_time", tsec[i]);
 
1845
      = secfile_lookup_int(file, "%s.mining_time", tsection);
1636
1846
 
1637
1847
    pterrain->transform_result
1638
 
      = lookup_terrain(secfile_lookup_str(file, "%s.transform_result",
1639
 
                                          tsec[i]), pterrain);
 
1848
      = lookup_terrain(file, "transform_result", pterrain);
1640
1849
    pterrain->transform_time
1641
 
      = secfile_lookup_int(file, "%s.transform_time", tsec[i]);
 
1850
      = secfile_lookup_int(file, "%s.transform_time", tsection);
1642
1851
    pterrain->rail_time
1643
 
      = secfile_lookup_int_default(file, 3, "%s.rail_time", tsec[i]);
1644
 
    pterrain->airbase_time
1645
 
      = secfile_lookup_int_default(file, 3, "%s.airbase_time", tsec[i]);
1646
 
    pterrain->fortress_time
1647
 
      = secfile_lookup_int_default(file, 3, "%s.fortress_time", tsec[i]);
 
1852
      = secfile_lookup_int_default(file, 3, "%s.rail_time", tsection);
1648
1853
    pterrain->clean_pollution_time
1649
 
      = secfile_lookup_int_default(file, 3, "%s.clean_pollution_time", tsec[i]);
 
1854
      = secfile_lookup_int_default(file, 3, "%s.clean_pollution_time", tsection);
1650
1855
    pterrain->clean_fallout_time
1651
 
      = secfile_lookup_int_default(file, 3, "%s.clean_fallout_time", tsec[i]);
 
1856
      = secfile_lookup_int_default(file, 3, "%s.clean_fallout_time", tsection);
1652
1857
 
1653
1858
    pterrain->warmer_wetter_result
1654
 
      = lookup_terrain(secfile_lookup_str(file, "%s.warmer_wetter_result",
1655
 
                                          tsec[i]), pterrain);
 
1859
      = lookup_terrain(file, "warmer_wetter_result", pterrain);
1656
1860
    pterrain->warmer_drier_result
1657
 
      = lookup_terrain(secfile_lookup_str(file, "%s.warmer_drier_result",
1658
 
                                          tsec[i]), pterrain);
 
1861
      = lookup_terrain(file, "warmer_drier_result", pterrain);
1659
1862
    pterrain->cooler_wetter_result
1660
 
      = lookup_terrain(secfile_lookup_str(file, "%s.cooler_wetter_result",
1661
 
                                          tsec[i]), pterrain);
 
1863
      = lookup_terrain(file, "cooler_wetter_result", pterrain);
1662
1864
    pterrain->cooler_drier_result
1663
 
      = lookup_terrain(secfile_lookup_str(file, "%s.cooler_drier_result",
1664
 
                                          tsec[i]), pterrain);
 
1865
      = lookup_terrain(file, "cooler_drier_result", pterrain);
1665
1866
 
1666
 
    slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsec[i]);
 
1867
    slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsection);
1667
1868
    BV_CLR_ALL(pterrain->flags);
1668
1869
    for (j = 0; j < nval; j++) {
1669
1870
      const char *sval = slist[j];
1670
1871
      enum terrain_flag_id flag = find_terrain_flag_by_rule_name(sval);
1671
1872
 
1672
1873
      if (flag == TER_LAST) {
1673
 
        freelog(LOG_FATAL, "\"%s\" [%s] has unknown flag \"%s\".",
1674
 
                filename, tsec[i], sval);
1675
 
        exit(EXIT_FAILURE);
 
1874
        ruleset_error(LOG_FATAL, "\"%s\" [%s] has unknown flag \"%s\".",
 
1875
                      filename, tsection, sval);
1676
1876
      } else {
1677
1877
        BV_SET(pterrain->flags, flag);
1678
1878
      }
1689
1889
 
1690
1890
      pterrain->property[j] = secfile_lookup_int_default(file, 0,
1691
1891
                                                         "%s.property_%s",
1692
 
                                                         tsec[i], mg_names[j]);
1693
 
    }
1694
 
 
1695
 
    pterrain->helptext = lookup_helptext(file, tsec[i]);
 
1892
                                                         tsection, mg_names[j]);
 
1893
    }
 
1894
 
 
1895
    slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
 
1896
    BV_CLR_ALL(pterrain->native_to);
 
1897
    for (j = 0; j < nval; j++) {
 
1898
      struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
 
1899
 
 
1900
      if (!class) {
 
1901
        ruleset_error(LOG_FATAL,
 
1902
                      "\"%s\" [%s] is native to unknown unit class \"%s\".",
 
1903
                      filename, tsection, slist[j]);
 
1904
      } else if (is_ocean(pterrain) && class->move_type == LAND_MOVING) {
 
1905
        ruleset_error(LOG_FATAL,
 
1906
                      "\"%s\" oceanic [%s] is native to land units.",
 
1907
                      filename, tsection);
 
1908
      } else if (!is_ocean(pterrain) && class->move_type == SEA_MOVING) {
 
1909
        ruleset_error(LOG_FATAL,
 
1910
                      "\"%s\" non-oceanic [%s] is native to sea units.",
 
1911
                      filename, tsection);
 
1912
      } else {
 
1913
        BV_SET(pterrain->native_to, uclass_index(class));
 
1914
      }
 
1915
    }
 
1916
    free(slist);
 
1917
 
 
1918
    pterrain->helptext = lookup_helptext(file, tsection);
1696
1919
  } terrain_type_iterate_end;
1697
 
  free(tsec);
1698
 
 
1699
 
  rsec = secfile_get_secnames_prefix(file, RESOURCE_SECTION_PREFIX, &nval);
 
1920
 
 
1921
  /* resource details */
 
1922
 
1700
1923
  resource_type_iterate(presource) {
1701
 
    const int i = presource->index;
 
1924
    char identifier[MAX_LEN_NAME];
 
1925
    const int i = resource_index(presource);
 
1926
    const char *rsection = &resource_sections[i * MAX_SECTION_LABEL];
1702
1927
 
1703
1928
    output_type_iterate (o) {
1704
1929
      presource->output[o] =
1705
 
          secfile_lookup_int_default(file, 0, "%s.%s", rsec[i],
 
1930
          secfile_lookup_int_default(file, 0, "%s.%s", rsection,
1706
1931
                                       get_output_identifier(o));
1707
1932
    } output_type_iterate_end;
1708
1933
    sz_strlcpy(presource->graphic_str,
1709
 
               secfile_lookup_str(file,"%s.graphic", rsec[i]));
 
1934
               secfile_lookup_str(file,"%s.graphic", rsection));
1710
1935
    sz_strlcpy(presource->graphic_alt,
1711
 
               secfile_lookup_str(file,"%s.graphic_alt", rsec[i]));
 
1936
               secfile_lookup_str(file,"%s.graphic_alt", rsection));
1712
1937
 
1713
 
    presource->identifier
1714
 
      = secfile_lookup_str(file, "%s.identifier", rsec[i])[0];
1715
 
    if ('\0' == presource->identifier) {
1716
 
      freelog(LOG_FATAL, "\"%s\" [%s] missing identifier.",
1717
 
              filename, rsec[i]);
1718
 
      exit(EXIT_FAILURE);
1719
 
    }
 
1938
    sz_strlcpy(identifier,
 
1939
               secfile_lookup_str(file,"%s.identifier", rsection));
 
1940
    presource->identifier = identifier[0];
1720
1941
    if (RESOURCE_NULL_IDENTIFIER == presource->identifier) {
1721
 
      freelog(LOG_FATAL, "\"%s\" [%s] cannot use '%c' as an identifier;"
1722
 
                         " it is reserved.",
1723
 
                filename, rsec[i], presource->identifier);
1724
 
      exit(EXIT_FAILURE);
 
1942
      ruleset_error(LOG_FATAL, "\"%s\" [%s] identifier missing value.",
 
1943
                    filename, rsection);
 
1944
    }
 
1945
    if (RESOURCE_NONE_IDENTIFIER == presource->identifier) {
 
1946
      ruleset_error(LOG_FATAL,
 
1947
                    "\"%s\" [%s] cannot use '%c' as an identifier;"
 
1948
                    " it is reserved.",
 
1949
                    filename, rsection, presource->identifier);
1725
1950
    }
1726
1951
    for (j = 0; j < i; j++) {
1727
1952
      if (presource->identifier == resource_by_number(j)->identifier) {
1728
 
        freelog(LOG_FATAL, "\"%s\" [%s] has the same identifier as \"%s\".",
1729
 
                filename,
1730
 
                rsec[i],
1731
 
                resource_rule_name(resource_by_number(j)));
1732
 
        exit(EXIT_FAILURE);
 
1953
        ruleset_error(LOG_FATAL,
 
1954
                      "\"%s\" [%s] has the same identifier as [%s].",
 
1955
                      filename,
 
1956
                      rsection,
 
1957
                      &resource_sections[j * MAX_SECTION_LABEL]);
1733
1958
      }
1734
1959
    }
 
1960
 
1735
1961
  } resource_type_iterate_end;
1736
 
  free(rsec);
 
1962
 
 
1963
  /* base details */
 
1964
  base_type_iterate(pbase) {
 
1965
    BV_CLR_ALL(pbase->conflicts);
 
1966
  } base_type_iterate_end;
 
1967
 
 
1968
  base_type_iterate(pbase) {
 
1969
    const char *section = &base_sections[base_index(pbase) * MAX_SECTION_LABEL];
 
1970
    int j;
 
1971
    char **slist;
 
1972
    struct requirement_vector *reqs;
 
1973
    char *gui_str;
 
1974
 
 
1975
    pbase->buildable = secfile_lookup_bool_default(file, TRUE,
 
1976
                                                  "%s.buildable", section);
 
1977
    pbase->pillageable = secfile_lookup_bool_default(file, TRUE,
 
1978
                                                     "%s.pillageable", section);
 
1979
 
 
1980
    sz_strlcpy(pbase->graphic_str,
 
1981
               secfile_lookup_str_default(file, "-", "%s.graphic", section));
 
1982
    sz_strlcpy(pbase->graphic_alt,
 
1983
               secfile_lookup_str_default(file, "-",
 
1984
                                          "%s.graphic_alt", section));
 
1985
    sz_strlcpy(pbase->activity_gfx,
 
1986
               secfile_lookup_str_default(file, "-",
 
1987
                                          "%s.activity_gfx", section));
 
1988
 
 
1989
    reqs = lookup_req_list(file, section, "reqs", base_rule_name(pbase));
 
1990
    requirement_vector_copy(&pbase->reqs, reqs);
 
1991
 
 
1992
    slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
 
1993
    BV_CLR_ALL(pbase->native_to);
 
1994
    for (j = 0; j < nval; j++) {
 
1995
      struct unit_class *class = find_unit_class_by_rule_name(slist[j]);
 
1996
 
 
1997
      if (!class) {
 
1998
        ruleset_error(LOG_FATAL,
 
1999
                      "\"%s\" base \"%s\" is native to unknown unit class \"%s\".",
 
2000
                      filename,
 
2001
                      base_rule_name(pbase),
 
2002
                      slist[j]);
 
2003
      } else {
 
2004
        BV_SET(pbase->native_to, uclass_index(class));
 
2005
      }
 
2006
    }
 
2007
    free(slist);
 
2008
 
 
2009
    gui_str = secfile_lookup_str(file,"%s.gui_type", section);
 
2010
    pbase->gui_type = base_gui_type_from_str(gui_str);
 
2011
    if (pbase->gui_type == BASE_GUI_LAST) {
 
2012
      ruleset_error(LOG_FATAL, "\"%s\" base \"%s\": unknown gui_type \"%s\".",
 
2013
                    filename,
 
2014
                    base_rule_name(pbase),
 
2015
                    gui_str);
 
2016
    }
 
2017
 
 
2018
    pbase->build_time = secfile_lookup_int(file, "%s.build_time", section);
 
2019
    pbase->border_sq  = secfile_lookup_int_default(file, -1, "%s.border_sq",
 
2020
                                                   section);
 
2021
    pbase->vision_main_sq   = secfile_lookup_int_default(file, -1,
 
2022
                                                         "%s.vision_main_sq",
 
2023
                                                         section);
 
2024
    pbase->vision_invis_sq  = secfile_lookup_int_default(file, -1,
 
2025
                                                         "%s.vision_invis_sq",
 
2026
                                                         section);
 
2027
    pbase->defense_bonus  = secfile_lookup_int_default(file, 0,
 
2028
                                                       "%s.defense_bonus",
 
2029
                                                       section);
 
2030
 
 
2031
    slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
 
2032
    BV_CLR_ALL(pbase->flags);
 
2033
    for (j = 0; j < nval; j++) {
 
2034
      const char *sval = slist[j];
 
2035
      enum base_flag_id flag = base_flag_from_str(sval);
 
2036
 
 
2037
      if (flag == BF_LAST) {
 
2038
        ruleset_error(LOG_FATAL, "\"%s\" base \"%s\": unknown flag \"%s\".",
 
2039
                      filename,
 
2040
                      base_rule_name(pbase),
 
2041
                      sval);
 
2042
      } else {
 
2043
        BV_SET(pbase->flags, flag);
 
2044
      }
 
2045
    }
 
2046
 
 
2047
    free(slist);
 
2048
 
 
2049
    slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
 
2050
    for (j = 0; j < nval; j++) {
 
2051
      const char *sval = slist[j];
 
2052
      struct base_type *pbase2 = find_base_type_by_rule_name(sval);
 
2053
 
 
2054
      if (pbase2 == NULL) {
 
2055
        ruleset_error(LOG_FATAL, "\"%s\" base \"%s\": unknown conflict base \"%s\".",
 
2056
                      filename,
 
2057
                      base_rule_name(pbase),
 
2058
                      sval);
 
2059
      } else {
 
2060
        BV_SET(pbase->conflicts, base_index(pbase2));
 
2061
        BV_SET(pbase2->conflicts, base_index(pbase));
 
2062
      }
 
2063
    }
 
2064
    
 
2065
    free(slist);
 
2066
 
 
2067
    if (territory_claiming_base(pbase)) {
 
2068
      base_type_iterate(pbase2) {
 
2069
        if (pbase2 > pbase && territory_claiming_base(pbase2)) {
 
2070
          BV_SET(pbase->conflicts, base_index(pbase2));
 
2071
          BV_SET(pbase2->conflicts, base_index(pbase));
 
2072
        }
 
2073
      } base_type_iterate_end;
 
2074
    }
 
2075
 
 
2076
  } base_type_iterate_end;
1737
2077
 
1738
2078
  section_file_check_unused(file, filename);
1739
2079
  section_file_free(file);
1752
2092
 
1753
2093
  sec = secfile_get_secnames_prefix(file, GOVERNMENT_SECTION_PREFIX, &nval);
1754
2094
  if (nval == 0) {
1755
 
    freelog(LOG_FATAL, "\"%s\": No governments?!?", filename);
1756
 
    exit(EXIT_FAILURE);
 
2095
    ruleset_error(LOG_FATAL, "\"%s\": No governments?!?", filename);
1757
2096
  } else if(nval > G_MAGIC) {
1758
2097
    /* upper limit is really about 255 for 8-bit id values, but
1759
2098
       use G_MAGIC elsewhere as a sanity check, and should be plenty
1760
2099
       big enough --dwp */
1761
 
    freelog(LOG_FATAL, "\"%s\": Too many governments (%d, max %d)",
1762
 
            filename, nval, G_MAGIC);
1763
 
    exit(EXIT_FAILURE);
 
2100
    ruleset_error(LOG_FATAL, "\"%s\": Too many governments (%d, max %d)",
 
2101
                  filename, nval, G_MAGIC);
1764
2102
  }
1765
2103
  governments_alloc(nval);
1766
2104
 
1767
2105
  /* Government names are needed early so that get_government_by_name will
1768
2106
   * work. */
1769
2107
  government_iterate(gov) {
1770
 
    char *name = secfile_lookup_str(file, "%s.name", sec[gov->index]);
 
2108
    char *name = secfile_lookup_str(file, "%s.name",
 
2109
                                    sec[government_index(gov)]);
1771
2110
 
1772
2111
    name_strlcpy(gov->name.vernacular, name);
1773
2112
    gov->name.translated = NULL;
1776
2115
}
1777
2116
 
1778
2117
/**************************************************************************
1779
 
...  
 
2118
  This loads information from given governments.ruleset
1780
2119
**************************************************************************/
1781
2120
static void load_ruleset_governments(struct section_file *file)
1782
2121
{
1788
2127
 
1789
2128
  sec = secfile_get_secnames_prefix(file, GOVERNMENT_SECTION_PREFIX, &nval);
1790
2129
 
1791
 
  game.government_when_anarchy
1792
 
    = lookup_government(file, "governments.when_anarchy", filename);
1793
 
  game.info.government_when_anarchy_id = game.government_when_anarchy->index;
 
2130
  game.government_during_revolution
 
2131
    = lookup_government(file, "governments.during_revolution", filename);
 
2132
  game.info.government_during_revolution_id =
 
2133
    government_number(game.government_during_revolution);
1794
2134
 
1795
2135
  /* easy ones: */
1796
2136
  government_iterate(g) {
1797
 
    int i = g->index;
1798
 
    struct requirement_vector *reqs = lookup_req_list(file, sec[i], "reqs",
1799
 
                                                      government_rule_name(g));
 
2137
    const int i = government_index(g);
 
2138
    struct requirement_vector *reqs =
 
2139
      lookup_req_list(file, sec[i], "reqs", government_rule_name(g));
1800
2140
 
1801
2141
    if (section_file_lookup(file, "%s.ai_better", sec[i])) {
1802
2142
      char entry[100];
1819
2159
  
1820
2160
  /* titles */
1821
2161
  government_iterate(g) {
1822
 
    int i = g->index;
1823
2162
    struct ruler_title *title;
 
2163
    const int i = government_index(g);
1824
2164
 
1825
2165
    g->num_ruler_titles = 1;
1826
2166
    g->ruler_titles = fc_calloc(1, sizeof(*g->ruler_titles));
1862
2202
/**************************************************************************
1863
2203
This checks if nations[pos] leader names are not already defined in any 
1864
2204
previous nation, or twice in its own leader name table.
1865
 
If not return NULL, if yes return pointer to name which is repeated.
 
2205
If not return NULL, if yes return pointer to name which is repeated
 
2206
and id of a conflicting nation as second parameter.
1866
2207
**************************************************************************/
1867
 
static char *check_leader_names(Nation_type_id nation)
 
2208
static char *check_leader_names(Nation_type_id nation,
 
2209
             Nation_type_id *conflict_nation)
1868
2210
{
1869
2211
  int k;
1870
2212
  struct nation_type *pnation = nation_by_number(nation);
1876
2218
 
1877
2219
    for (i = 0; i < k; i++) {
1878
2220
      if (0 == strcmp(leader, pnation->leaders[i].name)) {
 
2221
        *conflict_nation = nation;
1879
2222
        return leader;
1880
2223
      }
1881
2224
    }
1885
2228
 
1886
2229
      for (i = 0; i < pnation2->leader_count; i++) {
1887
2230
        if (0 == strcmp(leader, pnation2->leaders[i].name)) {
 
2231
          *conflict_nation = nation2;
1888
2232
          return leader;
1889
2233
        }
1890
2234
      }
1922
2266
 
1923
2267
      if (0 == strcmp(n2->adjective.vernacular, pl->adjective.vernacular)
1924
2268
        || 0 == strcmp(n2->noun_plural.vernacular, pl->noun_plural.vernacular)) {
1925
 
        freelog(LOG_FATAL,
1926
 
                "%s nation (the %s) defined twice; "
1927
 
                "in section nation%d and section nation%d",
1928
 
                adjective, noun_plural, j, i);
1929
 
        exit(EXIT_FAILURE);
 
2269
        ruleset_error(LOG_FATAL,
 
2270
                      "%s nation (the %s) defined twice; "
 
2271
                      "in section nation%d and section nation%d",
 
2272
                      adjective, noun_plural, j, i);
1930
2273
      }
1931
2274
    }
1932
2275
  } nations_iterate_end;
1947
2290
  int value;
1948
2291
 
1949
2292
  /* First we read the strings from the section file (above). */
1950
 
  char **cities = secfile_lookup_str_vec(file, &dim, "%s%s",
 
2293
  char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
1951
2294
                                         secfile_str1, secfile_str2);
1952
2295
 
1953
2296
  /*
1978
2321
     * a lot of ugly string handling...
1979
2322
     */
1980
2323
    memset(city_names[j].terrain, 0,
1981
 
           T_COUNT * sizeof(city_names[j].terrain[0]));
 
2324
           terrain_count() * sizeof(city_names[j].terrain[0]));
1982
2325
    city_names[j].river = 0;
1983
2326
 
1984
2327
    if (name) {
1988
2331
       */
1989
2332
      char *next = strchr(name + 1, ')');
1990
2333
      if (!next) {
1991
 
        freelog(LOG_FATAL,
1992
 
                "Badly formed city name %s in city name "
1993
 
                "ruleset \"%s%s\": unmatched parenthesis.",
1994
 
                cities[j], secfile_str1, secfile_str2);
1995
 
        assert(FALSE);
 
2334
        ruleset_error(LOG_ERROR,
 
2335
                      "\"%s\" [%s] %s: city name \"%s\" unmatched parenthesis.",
 
2336
                      secfile_filename(file),
 
2337
                      secfile_str1,
 
2338
                      secfile_str2,
 
2339
                      cities[j]);
1996
2340
      } else { /* if (!next) */
1997
2341
        name[0] = next[0] = '\0';
1998
2342
        name++;
2023
2367
          } else {
2024
2368
            /* "handled" tracks whether we find a match (for error handling) */
2025
2369
            bool handled = FALSE;
 
2370
            int l = strlen(name);
 
2371
 
 
2372
            if (l > 0  && 's' == my_tolower(name[l-1])) {
 
2373
              /* remove frequent trailing 's' */
 
2374
              name[--l] = '\0';
 
2375
            }
2026
2376
 
2027
2377
            terrain_type_iterate(pterrain) {
 
2378
              const int i = terrain_index(pterrain);
 
2379
              const char *isection = &terrain_sections[i * MAX_SECTION_LABEL];
2028
2380
              /*
2029
 
               * Note that at this point, the name fields contain an
2030
 
               * untranslated string.  Note that name of T_RIVER_UNUSED is "".
2031
 
               * However, this is not a problem -- we don't use the translated
2032
 
               * name for comparison, and handle rivers separately.
 
2381
               * Note that the section name is unique (by definition).
 
2382
               * The sub-strings are carefully crafted for this function.
2033
2383
               */
2034
 
              if (0 == mystrcasecmp(terrain_rule_name(pterrain), name)) {
2035
 
                city_names[j].terrain[pterrain->index] = setting;
 
2384
              if (NULL != mystrcasestr(isection, name)) {
 
2385
                city_names[j].terrain[i] = setting;
2036
2386
                handled = TRUE;
2037
2387
                break;
2038
2388
              }
2039
2389
            } terrain_type_iterate_end;
2040
2390
            if (!handled) {
2041
 
              freelog(LOG_FATAL, "Unreadable terrain description %s "
2042
 
                      "in city name ruleset \"%s%s\" - skipping it.",
2043
 
                      name, secfile_str1, secfile_str2);
2044
 
              assert(FALSE); /* FIXME, not skipped! */
 
2391
              ruleset_error(LOG_ERROR,
 
2392
                            "\"%s\" [%s] %s: terrain \"%s\" not found;"
 
2393
                            " skipping it.",
 
2394
                            secfile_filename(file),
 
2395
                            secfile_str1,
 
2396
                            secfile_str2,
 
2397
                            name);
2045
2398
            }
2046
2399
          }
2047
2400
          name = next ? next + 1 : NULL;
2053
2406
    if (check_name(city_names[j].name)) {
2054
2407
      /* The ruleset contains a name that is too long.  This shouldn't
2055
2408
         happen - if it does, the author should get immediate feedback */
2056
 
      freelog(LOG_FATAL, "City name %s in ruleset for %s%s is too long "
2057
 
              "- shortening it.",
2058
 
              city_names[j].name, secfile_str1, secfile_str2);
2059
 
      assert(FALSE); /* FIXME, not shortened! */
 
2409
      ruleset_error(LOG_ERROR, 
 
2410
                    "\"%s\" [%s] %s: city name \"%s\" is too long;"
 
2411
                    " shortening it.",
 
2412
                    secfile_filename(file),
 
2413
                    secfile_str1,
 
2414
                    secfile_str2,
 
2415
                    city_names[j].name);
2060
2416
      city_names[j].name[MAX_LEN_NAME - 1] = '\0';
2061
2417
    }
2062
2418
  }
2073
2429
{
2074
2430
  char *bad_leader, *govern;
2075
2431
  struct government *gov;
2076
 
  int dim, i, j, k, nval, numgroups;
 
2432
  int dim, i, i2, j, k, nval, numgroups;
2077
2433
  char temp_name[MAX_LEN_NAME];
2078
2434
  char **leaders, **sec, **civilwar_nations, **groups, **conflicts;
2079
2435
  char* name;
 
2436
  int barb_land_count = 0;
 
2437
  int barb_sea_count = 0;
2080
2438
  const char *filename = secfile_filename(file);
2081
 
  int barbarians = 0;
2082
2439
 
2083
2440
  (void) check_ruleset_capabilities(file, "+1.9", filename);
2084
2441
  
2096
2453
  nations_iterate(pl) {
2097
2454
    const int i = nation_index(pl);
2098
2455
    char tmp[200] = "\0";
 
2456
    char *barb_type;
2099
2457
 
2100
2458
    groups = secfile_lookup_str_vec(file, &dim, "%s.groups", sec[i]);
2101
2459
    pl->num_groups = dim;
2134
2492
              dim);
2135
2493
      dim = MAX_NUM_LEADERS;
2136
2494
    } else if (dim < 1) {
2137
 
      freelog(LOG_FATAL,
2138
 
              "Nation %s: number of leaders is %d; at least one is required.",
2139
 
              nation_rule_name(pl),
2140
 
              dim);
2141
 
      exit(EXIT_FAILURE);
 
2495
      ruleset_error(LOG_FATAL,
 
2496
                    "Nation %s: number of leaders is %d; at least one is required.",
 
2497
                    nation_rule_name(pl),
 
2498
                    dim);
2142
2499
    }
2143
2500
    pl->leader_count = dim;
2144
2501
    pl->leaders = fc_calloc(dim /*exact*/, sizeof(*(pl->leaders)));
2152
2509
    free(leaders);
2153
2510
 
2154
2511
    /* check if leader name is not already defined */
2155
 
    if( (bad_leader=check_leader_names(i)) ) {
2156
 
        freelog(LOG_FATAL, "Nation %s: leader %s defined more than once",
2157
 
                nation_rule_name(pl),
2158
 
                bad_leader);
2159
 
        exit(EXIT_FAILURE);
 
2512
    if ((bad_leader = check_leader_names(i, &i2))) {
 
2513
        if (i == i2) {
 
2514
          ruleset_error(LOG_FATAL,
 
2515
                        "Nation %s: leader \"%s\" defined more than once.",
 
2516
                        nation_rule_name(pl),
 
2517
                        bad_leader);
 
2518
        } else {
 
2519
          ruleset_error(LOG_FATAL,
 
2520
                        "Nations %s and %s share the same leader \"%s\".",
 
2521
                        nation_rule_name(pl),
 
2522
                        nation_rule_name(nation_by_number(i2)),
 
2523
                        bad_leader);
 
2524
        }
2160
2525
    }
2161
2526
    /* read leaders'sexes */
2162
2527
    leaders = secfile_lookup_str_vec(file, &dim, "%s.leader_sex", sec[i]);
2163
2528
    if (dim != pl->leader_count) {
2164
 
      freelog(LOG_FATAL,
2165
 
              "Nation %s: the leader sex count (%d) "
2166
 
              "is not equal to the number of leaders (%d)",
2167
 
              nation_rule_name(pl),
2168
 
              dim,
2169
 
              pl->leader_count);
2170
 
      exit(EXIT_FAILURE);
 
2529
      ruleset_error(LOG_FATAL,
 
2530
                    "Nation %s: the leader sex count (%d) "
 
2531
                    "is not equal to the number of leaders (%d)",
 
2532
                    nation_rule_name(pl),
 
2533
                    dim,
 
2534
                    pl->leader_count);
2171
2535
    }
2172
2536
    for (j = 0; j < dim; j++) {
2173
2537
      if (0 == mystrcasecmp(leaders[j], "Male")) {
2191
2555
    pl->is_playable = secfile_lookup_bool_default(file, TRUE,
2192
2556
                                                  "%s.is_playable", sec[i]);
2193
2557
    if (pl->is_playable) {
2194
 
      game.playable_nations++;
 
2558
      server.playable_nations++;
2195
2559
    }
2196
 
    pl->is_barbarian = secfile_lookup_bool_default(file, FALSE,
2197
 
                                                  "%s.is_barbarian", sec[i]);
2198
2560
 
2199
 
    if (pl->is_barbarian) {
2200
 
      if (pl->is_playable) {
2201
 
        /* We can't allow players to use barbarian nations, barbarians
2202
 
         * may run out of nations */
2203
 
        /* TRANS: Ruleset error */
2204
 
        freelog(LOG_FATAL, "Nation %s marked both barbarian and playable.",
2205
 
                nation_rule_name(pl));
2206
 
        exit(EXIT_FAILURE);
2207
 
      }
2208
 
      barbarians++;
 
2561
    /* Check barbarian type. Default is "None" meaning not a barbarian */    
 
2562
    barb_type = secfile_lookup_str_default(file, "None",
 
2563
                                           "%s.barbarian_type", sec[i]);
 
2564
    if (mystrcasecmp(barb_type, "None") == 0) {
 
2565
      pl->barb_type = NOT_A_BARBARIAN;
 
2566
    } else if (mystrcasecmp(barb_type, "Land") == 0) {
 
2567
      if (pl->is_playable) {
 
2568
        /* We can't allow players to use barbarian nations, barbarians
 
2569
         * may run out of nations */
 
2570
        ruleset_error(LOG_FATAL,
 
2571
                      "Nation %s marked both barbarian and playable.",
 
2572
                      nation_rule_name(pl));
 
2573
      }
 
2574
      pl->barb_type = LAND_BARBARIAN;
 
2575
      barb_land_count++;
 
2576
    } else if (mystrcasecmp(barb_type, "Sea") == 0) {
 
2577
      if (pl->is_playable) {
 
2578
        /* We can't allow players to use barbarian nations, barbarians
 
2579
         * may run out of nations */
 
2580
        ruleset_error(LOG_FATAL,
 
2581
                      "Nation %s marked both barbarian and playable.",
 
2582
                      nation_rule_name(pl));
 
2583
      }
 
2584
      pl->barb_type = SEA_BARBARIAN;
 
2585
      barb_sea_count++;
 
2586
    } else {
 
2587
      ruleset_error(LOG_FATAL,
 
2588
                    "Nation %s, barbarian_type is \"%s\". Must be "
 
2589
                    "\"None\" or \"Land\" or \"Sea\".",
 
2590
                    nation_rule_name(pl),
 
2591
                    barb_type);
2209
2592
    }
2210
2593
 
2211
2594
    /* Flags */
2212
2595
 
2213
2596
    sz_strlcpy(pl->flag_graphic_str,
2214
 
               secfile_lookup_str(file, "%s.flag", sec[i]));
 
2597
               secfile_lookup_str_default(file, "-", "%s.flag", sec[i]));
2215
2598
    sz_strlcpy(pl->flag_graphic_alt,
2216
 
               secfile_lookup_str(file, "%s.flag_alt", sec[i]));
 
2599
               secfile_lookup_str_default(file, "-", "%s.flag_alt", sec[i]));
2217
2600
 
2218
2601
    /* Ruler titles */
2219
2602
 
2271
2654
 
2272
2655
    while (city_style_has_requirements(&city_styles[pl->city_style])) {
2273
2656
      if (pl->city_style == 0) {
2274
 
        freelog(LOG_FATAL,
2275
 
               "Nation %s: the default city style is not available "
2276
 
               "from the beginning!",
2277
 
               nation_rule_name(pl));
 
2657
        ruleset_error(LOG_FATAL,
 
2658
                      "Nation %s: the default city style is not available "
 
2659
                      "from the beginning!",
 
2660
                      nation_rule_name(pl));
2278
2661
        /* Note that we can't use temp_name here. */
2279
 
        exit(EXIT_FAILURE);
2280
2662
      }
2281
2663
      freelog(LOG_ERROR,
2282
2664
              "Nation %s: city style \"%s\" is not available from beginning; "
2318
2700
    lookup_tech_list(file, sec[i], "init_techs", pl->init_techs, filename);
2319
2701
    lookup_building_list(file, sec[i], "init_buildings", pl->init_buildings,
2320
2702
                         filename);
2321
 
    lookup_unit_list(file, sec[i], "init_units", pl->init_units, filename,
2322
 
                     FALSE);
 
2703
    lookup_unit_list(file, sec[i], "init_units", LOG_ERROR, pl->init_units,
 
2704
                     filename);
2323
2705
    mystrlcat(tmp, sec[i], 200);
2324
2706
    mystrlcat(tmp, ".init_government", 200);
2325
2707
    pl->init_government = lookup_government(file, tmp, filename);
2326
2708
 
2327
2709
    /* read "normal" city names */
2328
2710
 
2329
 
    pl->city_names = load_city_name_list(file, sec[i], ".cities");
 
2711
    pl->city_names = load_city_name_list(file, sec[i], "cities");
2330
2712
 
2331
2713
    pl->legend = mystrdup(secfile_lookup_str(file, "%s.legend", sec[i]));
2332
2714
    if (check_strlen(pl->legend, MAX_LEN_MSG, "Legend '%s' is too long")) {
2360
2742
  section_file_check_unused(file, filename);
2361
2743
  section_file_free(file);
2362
2744
 
2363
 
  if (barbarians < 1) {
2364
 
    /* TRANS: Ruleset error */
2365
 
    freelog(LOG_FATAL,
2366
 
            _("No barbarian nation in rulesets, at least one required!"));
2367
 
    exit(EXIT_FAILURE);
 
2745
  if (barb_land_count == 0) {
 
2746
    ruleset_error(LOG_FATAL,
 
2747
                  "No land barbarian nation defined. At least one required!");
 
2748
  }
 
2749
  if (barb_sea_count == 0) {
 
2750
    ruleset_error(LOG_FATAL,
 
2751
                  "No sea barbarian nation defined. At least one required!");
2368
2752
  }
2369
2753
}
2370
2754
 
2405
2789
 
2406
2790
  /* Specialist options */
2407
2791
  sec = secfile_get_secnames_prefix(file, SPECIALIST_SECTION_PREFIX, &nval);
 
2792
  if (nval >= SP_MAX) {
 
2793
    ruleset_error(LOG_FATAL, "\"%s\": Too many specialists (%d, max %d).",
 
2794
            filename, nval, SP_MAX);
 
2795
  }
 
2796
  game.control.num_specialist_types = nval;
2408
2797
 
2409
2798
  for (i = 0; i < nval; i++) {
2410
 
    struct specialist *s = &specialists[i];
 
2799
    struct specialist *s = specialist_by_number(i);
2411
2800
    struct requirement_vector *reqs;
2412
2801
 
2413
2802
    item = secfile_lookup_str(file, "%s.name", sec[i]);
2414
 
    sz_strlcpy(s->name, item);
2415
 
 
2416
 
    item = secfile_lookup_str_default(file, s->name, "%s.short_name", sec[i]);
2417
 
    sz_strlcpy(s->short_name, item);
2418
 
 
2419
 
    reqs = lookup_req_list(file, sec[i], "reqs", s->name);
 
2803
    sz_strlcpy(s->name.vernacular, item);
 
2804
    s->name.translated = NULL;
 
2805
 
 
2806
    item = secfile_lookup_str_default(file, s->name.vernacular,
 
2807
                                      "%s.short_name",
 
2808
                                      sec[i]);
 
2809
    sz_strlcpy(s->abbreviation.vernacular, item);
 
2810
    s->abbreviation.translated = NULL;
 
2811
 
 
2812
    reqs = lookup_req_list(file, sec[i], "reqs", specialist_rule_name(s));
2420
2813
    requirement_vector_copy(&s->reqs, reqs);
2421
2814
 
2422
2815
    if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
2424
2817
    }
2425
2818
  }
2426
2819
  if (DEFAULT_SPECIALIST == -1) {
2427
 
    freelog(LOG_FATAL, "\"%s\": must give a min_size of 0 for at least one "
2428
 
            "specialist type.", filename);
2429
 
    exit(EXIT_FAILURE);
 
2820
    ruleset_error(LOG_FATAL,
 
2821
                  "\"%s\": must give a min_size of 0 for at least one "
 
2822
                  "specialist type.", filename);
2430
2823
  }
2431
 
  SP_COUNT = nval;
2432
2824
  free(sec);
2433
2825
 
2434
2826
  /* City Parameters */
2452
2844
    secfile_lookup_int_default(file, 0, "parameters.forced_gold");
2453
2845
  if (game.info.forced_science + game.info.forced_luxury
2454
2846
      + game.info.forced_gold != 100) {
2455
 
    freelog(LOG_FATAL, "\"%s\": Forced taxes do not add up in ruleset!",
2456
 
            filename);
2457
 
    exit(EXIT_FAILURE);
 
2847
    ruleset_error(LOG_FATAL,
 
2848
                  "\"%s\": Forced taxes do not add up in ruleset!",
 
2849
                  filename);
2458
2850
  }
2459
2851
 
 
2852
  /* civ1 & 2 didn't reveal tiles */
 
2853
  game.info.vision_reveal_tiles =
 
2854
    secfile_lookup_bool_default(file, FALSE, "parameters.vision_reveal_tiles");
 
2855
 
2460
2856
  /* City Styles ... */
2461
2857
 
2462
2858
  styles = secfile_get_secnames_prefix(file, CITYSTYLE_SECTION_PREFIX, &nval);
2469
2865
               secfile_lookup_str(file, "%s.graphic", styles[i]));
2470
2866
    sz_strlcpy(city_styles[i].graphic_alt, 
2471
2867
               secfile_lookup_str(file, "%s.graphic_alt", styles[i]));
2472
 
    sz_strlcpy(city_styles[i].citizens_graphic, 
 
2868
    sz_strlcpy(city_styles[i].oceanic_graphic, 
 
2869
               secfile_lookup_str_default(file, "",
 
2870
                                          "%s.oceanic_graphic", styles[i]));
 
2871
    sz_strlcpy(city_styles[i].oceanic_graphic_alt, 
 
2872
               secfile_lookup_str_default(file, "",
 
2873
                                          "%s.oceanic_graphic_alt", styles[i]));
 
2874
    sz_strlcpy(city_styles[i].citizens_graphic,
2473
2875
               secfile_lookup_str_default(file, "-", 
2474
2876
                        "%s.citizens_graphic", styles[i]));
2475
2877
    sz_strlcpy(city_styles[i].citizens_graphic_alt, 
2553
2955
}
2554
2956
 
2555
2957
/**************************************************************************
2556
 
Load ruleset file
 
2958
  Load ruleset file.
2557
2959
**************************************************************************/
2558
2960
static void load_ruleset_game(void)
2559
2961
{
2562
2964
  const char *filename;
2563
2965
  int *food_ini;
2564
2966
  int i;
2565
 
  char *tileset;
 
2967
  char *text;
2566
2968
 
2567
2969
  openload_ruleset_file(&file, "game");
2568
2970
  filename = secfile_filename(&file);
 
2971
 
 
2972
  /* section: datafile */
2569
2973
  (void) check_ruleset_capabilities(&file, "+1.11.1", filename);
2570
2974
  (void) section_file_lookup(&file, "datafile.description");    /* unused */
2571
2975
 
2572
 
  tileset = secfile_lookup_str_default(&file, "", "tileset.prefered");
2573
 
  if (tileset[0] != '\0') {
 
2976
  /* section: tileset */
 
2977
  text = secfile_lookup_str_default(&file, "", "tileset.prefered");
 
2978
  if (text[0] != '\0') {
2574
2979
    /* There was tileset suggestion */
2575
 
    sz_strlcpy(game.control.prefered_tileset, tileset);
 
2980
    sz_strlcpy(game.control.prefered_tileset, text);
2576
2981
  } else {
2577
2982
    /* No tileset suggestions */
2578
2983
    game.control.prefered_tileset[0] = '\0';
2579
2984
  }
2580
2985
 
2581
 
  game.info.base_pollution = 
2582
 
        secfile_lookup_int_default(&file, -20, "civstyle.base_pollution");
2583
 
  game.info.happy_cost =
2584
 
        secfile_lookup_int_default(&file, 2, "civstyle.happy_cost");
2585
 
  game.info.food_cost =
2586
 
        secfile_lookup_int_default(&file, 2, "civstyle.food_cost");
2587
 
  game.info.base_bribe_cost =
2588
 
        secfile_lookup_int_default(&file, 750, "civstyle.base_bribe_cost");
2589
 
  game.info.ransom_gold =
2590
 
        secfile_lookup_int_default(&file, 100, "civstyle.ransom_gold");
2591
 
  game.info.base_tech_cost =
2592
 
        secfile_lookup_int_default(&file, 20, "civstyle.base_tech_cost");
2593
 
 
2594
 
  output_type_iterate(o) {
2595
 
    game.info.min_city_center_output[o]
2596
 
      = secfile_lookup_int_default(&file, 0,
2597
 
                                   "civstyle.min_city_center_%s",
2598
 
                                   get_output_identifier(o));
2599
 
  } output_type_iterate_end;
2600
 
 
2601
 
  /* This only takes effect if citymindist is set to 0. */
2602
 
  game.info.min_dist_bw_cities
2603
 
    = secfile_lookup_int(&file, "civstyle.min_dist_bw_cities");
2604
 
  if (game.info.min_dist_bw_cities < 1) {
2605
 
    freelog(LOG_ERROR, "Bad value %i for min_dist_bw_cities. Using 2.",
2606
 
            game.info.min_dist_bw_cities);
2607
 
    game.info.min_dist_bw_cities = 2;
2608
 
  }
2609
 
 
2610
 
  game.info.init_vis_radius_sq =
2611
 
    secfile_lookup_int(&file, "civstyle.init_vis_radius_sq");
2612
 
 
2613
 
  sval = secfile_lookup_str(&file, "civstyle.hut_overflight" );
2614
 
  if (mystrcasecmp(sval, "Nothing") == 0) {
2615
 
    game.info.hut_overflight = OVERFLIGHT_NOTHING;
2616
 
  } else if (mystrcasecmp(sval, "Frighten") == 0) {
2617
 
    game.info.hut_overflight = OVERFLIGHT_FRIGHTEN;
2618
 
  } else {
2619
 
    freelog(LOG_ERROR, "Bad value %s for hut_overflight. Using "
2620
 
            "\"Frighten\".", sval);
2621
 
    game.info.hut_overflight = OVERFLIGHT_FRIGHTEN;
2622
 
  }
2623
 
 
2624
 
  game.info.pillage_select =
2625
 
      secfile_lookup_bool(&file, "civstyle.pillage_select");
2626
 
 
2627
 
  sval = secfile_lookup_str(&file, "civstyle.nuke_contamination" );
2628
 
  if (mystrcasecmp(sval, "Pollution") == 0) {
2629
 
    game.info.nuke_contamination = CONTAMINATION_POLLUTION;
2630
 
  } else if (mystrcasecmp(sval, "Fallout") == 0) {
2631
 
    game.info.nuke_contamination = CONTAMINATION_FALLOUT;
2632
 
  } else {
2633
 
    freelog(LOG_ERROR, "Bad value %s for nuke_contamination. Using "
2634
 
            "\"Pollution\".", sval);
2635
 
    game.info.nuke_contamination = CONTAMINATION_POLLUTION;
2636
 
  }
2637
 
 
2638
 
  food_ini = secfile_lookup_int_vec(&file, &game.info.granary_num_inis, 
2639
 
                                    "civstyle.granary_food_ini");
 
2986
  /* section: about */
 
2987
  text = secfile_lookup_str(&file, "about.name");
 
2988
  /* Ruleset/modpack name found */
 
2989
  sz_strlcpy(game.control.name, text);
 
2990
 
 
2991
  text = secfile_lookup_str_default(&file, "", "about.description");
 
2992
  if (text[0] != '\0') {
 
2993
    /* Ruleset/modpack description found */
 
2994
    sz_strlcpy(game.control.description, text);
 
2995
  } else {
 
2996
    /* No description */
 
2997
    game.control.description[0] = '\0';
 
2998
  }
 
2999
 
 
3000
  /* section: options */
 
3001
  lookup_tech_list(&file, "options", "global_init_techs",
 
3002
                   game.server.rgame.global_init_techs, filename);
 
3003
  lookup_building_list(&file, "options", "global_init_buildings",
 
3004
                       game.server.rgame.global_init_buildings, filename);
 
3005
 
 
3006
  /* section: civstyle */
 
3007
  game.info.base_pollution
 
3008
    = secfile_lookup_int_default(&file, RS_DEFAULT_BASE_POLLUTION,
 
3009
                                 "civstyle.base_pollution");
 
3010
  game.info.happy_cost
 
3011
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3012
                                         RS_DEFAULT_HAPPY_COST,
 
3013
                                         RS_MIN_HAPPY_COST,
 
3014
                                         RS_MAX_HAPPY_COST,
 
3015
                                         "civstyle.happy_cost");
 
3016
  game.info.food_cost
 
3017
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3018
                                         RS_DEFAULT_FOOD_COST,
 
3019
                                         RS_MIN_FOOD_COST,
 
3020
                                         RS_MAX_FOOD_COST,
 
3021
                                         "civstyle.food_cost");
 
3022
  /* TODO: move to global_unit_options */
 
3023
  game.info.base_bribe_cost
 
3024
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3025
                                         RS_DEFAULT_BASE_BRIBE_COST,
 
3026
                                         RS_MIN_BASE_BRIBE_COST,
 
3027
                                         RS_MAX_BASE_BRIBE_COST,
 
3028
                                         "civstyle.base_bribe_cost");
 
3029
  /* TODO: move to global_unit_options */
 
3030
  game.info.ransom_gold
 
3031
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3032
                                         RS_DEFAULT_RANSOM_GOLD,
 
3033
                                         RS_MIN_RANSOM_GOLD,
 
3034
                                         RS_MAX_RANSOM_GOLD,
 
3035
                                         "civstyle.ransom_gold");
 
3036
  /* TODO: move to global_unit_options */
 
3037
  game.info.pillage_select
 
3038
    = secfile_lookup_bool_default(&file, RS_DEFAULT_PILLAGE_SELECT,
 
3039
                                         "civstyle.pillage_select");
 
3040
  /* TODO: move to global_unit_options */
 
3041
  game.info.upgrade_veteran_loss
 
3042
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3043
                                         RS_DEFAULT_UPGRADE_VETERAN_LOSS,
 
3044
                                         RS_MIN_UPGRADE_VETERAN_LOSS,
 
3045
                                         RS_MAX_UPGRADE_VETERAN_LOSS,
 
3046
                                         "civstyle.upgrade_veteran_loss");
 
3047
  /* TODO: move to global_unit_options */
 
3048
  game.info.autoupgrade_veteran_loss
 
3049
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3050
                                         RS_DEFAULT_UPGRADE_VETERAN_LOSS,
 
3051
                                         RS_MIN_UPGRADE_VETERAN_LOSS,
 
3052
                                         RS_MAX_UPGRADE_VETERAN_LOSS,
 
3053
                                         "civstyle.autoupgrade_veteran_loss");
 
3054
  /* TODO: move to new section research */
 
3055
  game.info.base_tech_cost
 
3056
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3057
                                         RS_DEFAULT_BASE_TECH_COST,
 
3058
                                         RS_MIN_BASE_TECH_COST,
 
3059
                                         RS_MAX_BASE_TECH_COST,
 
3060
                                         "civstyle.base_tech_cost");
 
3061
 
 
3062
  food_ini = secfile_lookup_int_vec(&file, &game.info.granary_num_inis,
 
3063
                                    "civstyle.granary_food_ini");
2640
3064
  if (game.info.granary_num_inis > MAX_GRANARY_INIS) {
2641
 
    freelog(LOG_FATAL,
2642
 
            "Too many granary_food_ini entries; %d is the maximum!",
2643
 
            MAX_GRANARY_INIS);
2644
 
    exit(EXIT_FAILURE);
 
3065
    ruleset_error(LOG_FATAL,
 
3066
                  "Too many granary_food_ini entries (%d, max %d)",
 
3067
                  game.info.granary_num_inis, MAX_GRANARY_INIS);
2645
3068
  } else if (game.info.granary_num_inis == 0) {
2646
 
    freelog(LOG_ERROR, "No values for granary_food_ini. Using 1.");
 
3069
    freelog(LOG_ERROR, "No values for granary_food_ini. Using default "
 
3070
                       "value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
2647
3071
    game.info.granary_num_inis = 1;
2648
 
    game.info.granary_food_ini[0] = 1;
 
3072
    game.info.granary_food_ini[0] = RS_DEFAULT_GRANARY_FOOD_INI;
2649
3073
  } else {
2650
3074
    int i;
2651
3075
 
2652
3076
    /* check for <= 0 entries */
2653
3077
    for (i = 0; i < game.info.granary_num_inis; i++) {
2654
3078
      if (food_ini[i] <= 0) {
2655
 
        if (i == 0) {
2656
 
          food_ini[i] = 1;
2657
 
        } else {
2658
 
          food_ini[i] = food_ini[i - 1];
2659
 
        }
2660
 
        freelog(LOG_ERROR, "Bad value for granary_food_ini[%i]. Using %i.",
2661
 
                i, food_ini[i]);
 
3079
        if (i == 0) {
 
3080
          food_ini[i] = RS_DEFAULT_GRANARY_FOOD_INI;
 
3081
        } else {
 
3082
          food_ini[i] = food_ini[i - 1];
 
3083
        }
 
3084
        freelog(LOG_ERROR, "Bad value for granary_food_ini[%i]. Using %i.",
 
3085
                i, food_ini[i]);
2662
3086
      }
2663
3087
      game.info.granary_food_ini[i] = food_ini[i];
2664
3088
    }
2665
3089
  }
2666
3090
  free(food_ini);
2667
3091
 
2668
 
  game.info.granary_food_inc =
2669
 
    secfile_lookup_int(&file, "civstyle.granary_food_inc");
2670
 
  if (game.info.granary_food_inc < 0) {
2671
 
    freelog(LOG_ERROR, "Bad value %i for granary_food_inc. Using 100.",
2672
 
            game.info.granary_food_inc);
2673
 
    game.info.granary_food_inc = 100;
2674
 
  }
2675
 
 
2676
 
  game.info.tech_cost_style =
2677
 
      secfile_lookup_int(&file, "civstyle.tech_cost_style");
2678
 
  if (game.info.tech_cost_style < 0 || game.info.tech_cost_style > 2) {
2679
 
    freelog(LOG_ERROR, "Bad value %i for tech_cost_style. Using 0.",
2680
 
            game.info.tech_cost_style);
2681
 
    game.info.tech_cost_style = 0;
2682
 
  }
2683
 
  game.info.tech_cost_double_year = 
2684
 
      secfile_lookup_int_default(&file, 1, "civstyle.tech_cost_double_year");
2685
 
 
2686
 
  game.info.autoupgrade_veteran_loss
2687
 
    = secfile_lookup_int(&file, "civstyle.autoupgrade_veteran_loss");
2688
 
 
2689
 
  game.info.tech_leakage =
2690
 
      secfile_lookup_int(&file, "civstyle.tech_leakage");
2691
 
  if (game.info.tech_leakage < 0 || game.info.tech_leakage > 3) {
2692
 
    freelog(LOG_ERROR, "Bad value %i for tech_leakage. Using 0.",
2693
 
            game.info.tech_leakage);
2694
 
    game.info.tech_leakage = 0;
2695
 
  }
2696
 
 
 
3092
  game.info.granary_food_inc
 
3093
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3094
                                         RS_DEFAULT_GRANARY_FOOD_INC,
 
3095
                                         RS_MIN_GRANARY_FOOD_INC,
 
3096
                                         RS_MAX_GRANARY_FOOD_INC,
 
3097
                                         "civstyle.granary_food_inc");
 
3098
 
 
3099
  output_type_iterate(o) {
 
3100
    game.info.min_city_center_output[o]
 
3101
      = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3102
                                           RS_DEFAULT_CITY_CENTER_OUTPUT,
 
3103
                                           RS_MIN_CITY_CENTER_OUTPUT,
 
3104
                                           RS_MAX_CITY_CENTER_OUTPUT,
 
3105
                                           "civstyle.min_city_center_%s",
 
3106
                                           get_output_identifier(o));
 
3107
  } output_type_iterate_end;
 
3108
 
 
3109
  sval = secfile_lookup_str(&file, "civstyle.nuke_contamination" );
 
3110
  if (mystrcasecmp(sval, "Pollution") == 0) {
 
3111
    game.info.nuke_contamination = CONTAMINATION_POLLUTION;
 
3112
  } else if (mystrcasecmp(sval, "Fallout") == 0) {
 
3113
    game.info.nuke_contamination = CONTAMINATION_FALLOUT;
 
3114
  } else {
 
3115
    freelog(LOG_ERROR, "Bad value %s for nuke_contamination. Using "
 
3116
            "\"Pollution\".", sval);
 
3117
    game.info.nuke_contamination = CONTAMINATION_POLLUTION;
 
3118
  }
 
3119
 
 
3120
  /* This only takes effect if citymindist is set to 0. */
 
3121
  game.info.min_dist_bw_cities
 
3122
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3123
                                         RS_DEFAULT_CITIES_MIN_DIST,
 
3124
                                         RS_MIN_CITIES_MIN_DIST,
 
3125
                                         RS_MAX_CITIES_MIN_DIST,
 
3126
                                         "civstyle.min_dist_bw_cities");
 
3127
  game.info.init_vis_radius_sq
 
3128
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3129
                                         RS_DEFAULT_VIS_RADIUS_SQ,
 
3130
                                         RS_MIN_VIS_RADIUS_SQ,
 
3131
                                         RS_MAX_VIS_RADIUS_SQ,
 
3132
                                         "civstyle.init_vis_radius_sq");
 
3133
 
 
3134
  game.info.gold_upkeep_style
 
3135
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3136
                                         RS_DEFAULT_GOLD_UPKEEP_STYLE,
 
3137
                                         RS_MIN_GOLD_UPKEEP_STYLE,
 
3138
                                         RS_MAX_GOLD_UPKEEP_STYLE,
 
3139
                                         "civstyle.gold_upkeep_style");
 
3140
 
 
3141
  /* TODO: move to new section research */
 
3142
  game.info.tech_cost_style
 
3143
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3144
                                         RS_DEFAULT_TECH_COST_STYLE,
 
3145
                                         RS_MIN_TECH_COST_STYLE,
 
3146
                                         RS_MAX_TECH_COST_STYLE,
 
3147
                                         "civstyle.tech_cost_style");
 
3148
  /* TODO: move to new section research */
 
3149
  game.info.tech_leakage
 
3150
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3151
                                         RS_DEFAULT_TECH_LEAKAGE,
 
3152
                                         RS_MIN_TECH_LEAKAGE,
 
3153
                                         RS_MAX_TECH_LEAKAGE,
 
3154
                                         "civstyle.tech_leakage");
2697
3155
  if (game.info.tech_cost_style == 0 && game.info.tech_leakage != 0) {
2698
3156
    freelog(LOG_ERROR,
2699
 
            "Only tech_leakage 0 supported with tech_cost_style 0.");
 
3157
            "Only tech_leakage 0 supported with tech_cost_style 0.");
2700
3158
    freelog(LOG_ERROR, "Switching to tech_leakage 0.");
2701
3159
    game.info.tech_leakage = 0;
2702
3160
  }
2703
 
    
2704
 
  /* City incite cost */
2705
 
  game.info.base_incite_cost =
2706
 
    secfile_lookup_int_default(&file, 1000, "incite_cost.base_incite_cost");
2707
 
  game.info.incite_improvement_factor = 
2708
 
    secfile_lookup_int_default(&file, 1, "incite_cost.improvement_factor");
2709
 
  game.info.incite_unit_factor = 
2710
 
    secfile_lookup_int_default(&file, 1, "incite_cost.unit_factor");
2711
 
  game.info.incite_total_factor = 
2712
 
    secfile_lookup_int_default(&file, 100, "incite_cost.total_factor");
2713
 
 
2714
 
  /* Slow invasions */
2715
 
  game.info.slow_invasions = 
2716
 
    secfile_lookup_bool_default(&file, GAME_DEFAULT_SLOW_INVASIONS,
2717
 
                                "global_unit_options.slow_invasions");
2718
 
  
2719
 
  /* Load global initial items. */
2720
 
  lookup_tech_list(&file, "options", "global_init_techs",
2721
 
                   game.rgame.global_init_techs, filename);
2722
 
  lookup_building_list(&file, "options", "global_init_buildings",
2723
 
                       game.rgame.global_init_buildings, filename);
2724
 
 
2725
 
  /* Enable/Disable killstack */
2726
 
  game.info.killstack = secfile_lookup_bool(&file, "combat_rules.killstack");
2727
 
 
 
3161
 
 
3162
  /* section: illness */
 
3163
  game.info.illness_on
 
3164
    = secfile_lookup_bool_default(&file, RS_DEFAULT_ILLNESS_ON,
 
3165
                                  "illness.illness_on");
 
3166
  game.info.illness_base_factor
 
3167
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3168
                                         RS_DEFAULT_ILLNESS_BASE_FACTOR,
 
3169
                                         RS_MIN_ILLNESS_BASE_FACTOR,
 
3170
                                         RS_MAX_ILLNESS_BASE_FACTOR,
 
3171
                                         "illness.illness_base_factor");
 
3172
  game.info.illness_min_size
 
3173
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3174
                                         RS_DEFAULT_ILLNESS_MIN_SIZE,
 
3175
                                         RS_MIN_ILLNESS_MIN_SIZE,
 
3176
                                         RS_MAX_ILLNESS_MIN_SIZE,
 
3177
                                         "illness.illness_min_size");
 
3178
  game.info.illness_trade_infection
 
3179
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3180
                                         RS_DEFAULT_ILLNESS_TRADE_INFECTION_PCT,
 
3181
                                         RS_MIN_ILLNESS_TRADE_INFECTION_PCT,
 
3182
                                         RS_MAX_ILLNESS_TRADE_INFECTION_PCT,
 
3183
                                         "illness.illness_trade_infection");
 
3184
  game.info.illness_pollution_factor
 
3185
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3186
                                         RS_DEFAULT_ILLNESS_POLLUTION_PCT,
 
3187
                                         RS_MIN_ILLNESS_POLLUTION_PCT,
 
3188
                                         RS_MAX_ILLNESS_POLLUTION_PCT,
 
3189
                                         "illness.illness_pollution_factor");
 
3190
 
 
3191
  /* section: incite_cost */
 
3192
  game.info.base_incite_cost
 
3193
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3194
                                         RS_DEFAULT_INCITE_BASE_COST,
 
3195
                                         RS_MIN_INCITE_BASE_COST,
 
3196
                                         RS_MAX_INCITE_BASE_COST,
 
3197
                                         "incite_cost.base_incite_cost");
 
3198
  game.info.incite_improvement_factor
 
3199
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3200
                                         RS_DEFAULT_INCITE_IMPROVEMENT_FCT,
 
3201
                                         RS_MIN_INCITE_IMPROVEMENT_FCT,
 
3202
                                         RS_MAX_INCITE_IMPROVEMENT_FCT,
 
3203
                                         "incite_cost.improvement_factor");
 
3204
  game.info.incite_unit_factor
 
3205
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3206
                                         RS_DEFAULT_INCITE_UNIT_FCT,
 
3207
                                         RS_MIN_INCITE_UNIT_FCT,
 
3208
                                         RS_MAX_INCITE_UNIT_FCT,
 
3209
                                         "incite_cost.unit_factor");
 
3210
  game.info.incite_total_factor
 
3211
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3212
                                         RS_DEFAULT_INCITE_TOTAL_FCT,
 
3213
                                         RS_MIN_INCITE_TOTAL_FCT,
 
3214
                                         RS_MAX_INCITE_TOTAL_FCT,
 
3215
                                         "incite_cost.total_factor");
 
3216
 
 
3217
  /* section: global_unit_options */
 
3218
  game.info.slow_invasions
 
3219
    = secfile_lookup_bool_default(&file, RS_DEFAULT_SLOW_INVASIONS,
 
3220
                                  "global_unit_options.slow_invasions");
 
3221
 
 
3222
  /* section: combat_rules */
 
3223
  game.info.killstack
 
3224
    = secfile_lookup_bool_default(&file, RS_DEFAULT_KILLSTACK,
 
3225
                                  "combat_rules.killstack");
 
3226
  game.info.tired_attack
 
3227
    = secfile_lookup_bool_default(&file, RS_DEFAULT_TIRED_ATTACK,
 
3228
                                  "combat_rules.tired_attack");
 
3229
 
 
3230
  /* section: borders */
 
3231
  game.info.border_city_radius_sq
 
3232
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3233
                                         RS_DEFAULT_BORDER_RADIUS_SQ_CITY,
 
3234
                                         RS_MIN_BORDER_RADIUS_SQ_CITY,
 
3235
                                         RS_MAX_BORDER_RADIUS_SQ_CITY,
 
3236
                                         "borders.radius_sq_city");
 
3237
  game.info.border_size_effect
 
3238
    = secfile_lookup_int_default_min_max(ruleset_error, &file,
 
3239
                                         RS_DEFAULT_BORDER_SIZE_EFFECT,
 
3240
                                         RS_MIN_BORDER_SIZE_EFFECT,
 
3241
                                         RS_MAX_BORDER_SIZE_EFFECT,
 
3242
                                         "borders.size_effect");
 
3243
 
 
3244
  /* section: calendar */
 
3245
  game.info.calendar_skip_0
 
3246
    = secfile_lookup_bool_default(&file, RS_DEFAULT_CALENDAR_SKIP_0,
 
3247
                                  "calendar.skip_year_0");
 
3248
  game.info.start_year
 
3249
    = secfile_lookup_int_default(&file, GAME_START_YEAR,
 
3250
                                 "calendar.start_year");
 
3251
  sz_strlcpy(game.info.positive_year_label,
 
3252
             _(secfile_lookup_str_default(&file,
 
3253
                                          RS_DEFAULT_POS_YEAR_LABEL,
 
3254
                                          "calendar.positive_label")));
 
3255
  sz_strlcpy(game.info.negative_year_label,
 
3256
             _(secfile_lookup_str_default(&file,
 
3257
                                          RS_DEFAULT_NEG_YEAR_LABEL,
 
3258
                                          "calendar.negative_label")));
 
3259
 
 
3260
  /* section: teams */
2728
3261
  svec = secfile_lookup_str_vec(&file, &game.info.num_teams, "teams.names");
2729
3262
  game.info.num_teams = MIN(MAX_NUM_TEAMS, game.info.num_teams);
2730
3263
  if (game.info.num_teams <= 0) {
2731
 
    freelog(LOG_FATAL, "Missing team names in game.ruleset.");
2732
 
    exit(EXIT_FAILURE);
 
3264
    ruleset_error(LOG_FATAL, "Missing team names in game.ruleset.");
2733
3265
  }
2734
3266
  for (i = 0; i < game.info.num_teams; i++) {
2735
3267
    sz_strlcpy(game.info.team_names_orig[i], svec[i]);
2741
3273
}
2742
3274
 
2743
3275
/**************************************************************************
 
3276
  Send the units ruleset information (all individual unit classes) to the
 
3277
  specified connections.
 
3278
**************************************************************************/
 
3279
static void send_ruleset_unit_classes(struct conn_list *dest)
 
3280
{
 
3281
  struct packet_ruleset_unit_class packet;
 
3282
 
 
3283
  unit_class_iterate(c) {
 
3284
    packet.id = uclass_number(c);
 
3285
    sz_strlcpy(packet.name, c->name.vernacular);
 
3286
    packet.move_type = c->move_type;
 
3287
    packet.min_speed = c->min_speed;
 
3288
    packet.hp_loss_pct = c->hp_loss_pct;
 
3289
    packet.hut_behavior = c->hut_behavior;
 
3290
    packet.flags = c->flags;
 
3291
 
 
3292
    lsend_packet_ruleset_unit_class(dest, &packet);
 
3293
  } unit_class_iterate_end;
 
3294
}
 
3295
 
 
3296
/**************************************************************************
2744
3297
  Send the units ruleset information (all individual units) to the
2745
3298
  specified connections.
2746
3299
**************************************************************************/
2750
3303
  int i;
2751
3304
 
2752
3305
  unit_type_iterate(u) {
2753
 
    packet.id = u->index;
 
3306
    packet.id = utype_number(u);
2754
3307
    sz_strlcpy(packet.name, u->name.vernacular);
2755
3308
    sz_strlcpy(packet.sound_move, u->sound_move);
2756
3309
    sz_strlcpy(packet.sound_move_alt, u->sound_move_alt);
2758
3311
    sz_strlcpy(packet.sound_fight_alt, u->sound_fight_alt);
2759
3312
    sz_strlcpy(packet.graphic_str, u->graphic_str);
2760
3313
    sz_strlcpy(packet.graphic_alt, u->graphic_alt);
2761
 
    packet.move_type = u->move_type;
2762
 
    packet.unit_class_id = utype_class(u)->id;
 
3314
    packet.unit_class_id = uclass_number(utype_class(u));
2763
3315
    packet.build_cost = u->build_cost;
2764
3316
    packet.pop_cost = u->pop_cost;
2765
3317
    packet.attack_strength = u->attack_strength;
2766
3318
    packet.defense_strength = u->defense_strength;
2767
3319
    packet.move_rate = u->move_rate;
2768
 
    packet.tech_requirement = u->tech_requirement;
2769
 
    packet.impr_requirement = u->impr_requirement;
2770
 
    packet.gov_requirement
2771
 
      = u->gov_requirement ? u->gov_requirement->index : -1;
 
3320
    packet.tech_requirement = u->require_advance
 
3321
                              ? advance_number(u->require_advance) : -1;
 
3322
    packet.impr_requirement = u->need_improvement
 
3323
                              ? improvement_number(u->need_improvement) : -1;
 
3324
    packet.gov_requirement = u->need_government
 
3325
                             ? government_number(u->need_government) : -1;
2772
3326
    packet.vision_radius_sq = u->vision_radius_sq;
2773
3327
    packet.transport_capacity = u->transport_capacity;
2774
3328
    packet.hp = u->hp;
2775
3329
    packet.firepower = u->firepower;
2776
 
    packet.obsoleted_by = u->obsoleted_by ? u->obsoleted_by->index : -1;
 
3330
    packet.obsoleted_by = u->obsoleted_by
 
3331
                          ? utype_number(u->obsoleted_by) : -1;
2777
3332
    packet.fuel = u->fuel;
2778
3333
    packet.flags = u->flags;
2779
3334
    packet.roles = u->roles;
2785
3340
    packet.paratroopers_mr_req = u->paratroopers_mr_req;
2786
3341
    packet.paratroopers_mr_sub = u->paratroopers_mr_sub;
2787
3342
    packet.bombard_rate = u->bombard_rate;
 
3343
    packet.city_size = u->city_size;
 
3344
    packet.cargo = u->cargo;
 
3345
    packet.targets = u->targets;
2788
3346
    for (i = 0; i < MAX_VET_LEVELS; i++) {
2789
3347
      sz_strlcpy(packet.veteran_name[i], u->veteran[i].name);
2790
3348
      packet.power_fact[i] = u->veteran[i].power_fact;
2809
3367
  struct packet_ruleset_specialist packet;
2810
3368
 
2811
3369
  specialist_type_iterate(spec_id) {
2812
 
    struct specialist *s = get_specialist(spec_id);
 
3370
    struct specialist *s = specialist_by_number(spec_id);
2813
3371
    int j;
2814
3372
 
2815
3373
    packet.id = spec_id;
2816
 
    sz_strlcpy(packet.name, s->name);
2817
 
    sz_strlcpy(packet.short_name, s->short_name);
 
3374
    sz_strlcpy(packet.name, s->name.vernacular);
 
3375
    sz_strlcpy(packet.short_name, s->abbreviation.vernacular);
2818
3376
    j = 0;
2819
3377
    requirement_vector_iterate(&s->reqs, preq) {
2820
3378
      packet.reqs[j++] = *preq;
2833
3391
{
2834
3392
  struct packet_ruleset_tech packet;
2835
3393
 
2836
 
  tech_type_iterate(tech_id) {
2837
 
    struct advance *a = &advances[tech_id];
2838
 
 
2839
 
    packet.id = tech_id;
 
3394
  advance_iterate(A_NONE, a) {
 
3395
    packet.id = advance_number(a);
2840
3396
    sz_strlcpy(packet.name, a->name.vernacular);
2841
3397
    sz_strlcpy(packet.graphic_str, a->graphic_str);
2842
3398
    sz_strlcpy(packet.graphic_alt, a->graphic_alt);
2843
 
    packet.req[0] = a->req[0];
2844
 
    packet.req[1] = a->req[1];
2845
 
    packet.root_req = a->root_req;
 
3399
 
 
3400
    packet.req[AR_ONE] = a->require[AR_ONE]
 
3401
                         ? advance_number(a->require[AR_ONE]) : -1;
 
3402
    packet.req[AR_TWO] = a->require[AR_TWO]
 
3403
                         ? advance_number(a->require[AR_TWO]) : -1;
 
3404
    packet.root_req = a->require[AR_ROOT]
 
3405
                      ? advance_number(a->require[AR_ROOT]) : -1;
 
3406
 
2846
3407
    packet.flags = a->flags;
2847
3408
    packet.preset_cost = a->preset_cost;
2848
3409
    packet.num_reqs = a->num_reqs;
2853
3414
    }
2854
3415
 
2855
3416
    lsend_packet_ruleset_tech(dest, &packet);
2856
 
  } tech_type_iterate_end;
 
3417
  } advance_iterate_end;
2857
3418
}
2858
3419
 
2859
3420
/**************************************************************************
2862
3423
**************************************************************************/
2863
3424
static void send_ruleset_buildings(struct conn_list *dest)
2864
3425
{
2865
 
  impr_type_iterate(i) {
2866
 
    struct impr_type *b = improvement_by_number(i);
 
3426
  improvement_iterate(b) {
2867
3427
    struct packet_ruleset_building packet;
2868
3428
    int j;
2869
3429
 
2870
 
    packet.id = i;
 
3430
    packet.id = improvement_number(b);
2871
3431
    packet.genus = b->genus;
2872
3432
    sz_strlcpy(packet.name, b->name.vernacular);
2873
3433
    sz_strlcpy(packet.graphic_str, b->graphic_str);
2877
3437
      packet.reqs[j++] = *preq;
2878
3438
    } requirement_vector_iterate_end;
2879
3439
    packet.reqs_count = j;
2880
 
    packet.obsolete_by = b->obsolete_by;
2881
 
    packet.replaced_by = b->replaced_by;
 
3440
    packet.obsolete_by = b->obsolete_by
 
3441
                         ? advance_number(b->obsolete_by) : -1;
 
3442
    packet.replaced_by = b->replaced_by
 
3443
                         ? improvement_number(b->replaced_by) : -1;
2882
3444
    packet.build_cost = b->build_cost;
2883
3445
    packet.upkeep = b->upkeep;
2884
3446
    packet.sabotage = b->sabotage;
2893
3455
    }
2894
3456
 
2895
3457
    lsend_packet_ruleset_building(dest, &packet);
2896
 
  } impr_type_iterate_end;
 
3458
  } improvement_iterate_end;
2897
3459
}
2898
3460
 
2899
3461
/**************************************************************************
2907
3469
  lsend_packet_ruleset_terrain_control(dest, &terrain_control);
2908
3470
 
2909
3471
  terrain_type_iterate(pterrain) {
2910
 
    const int i = pterrain->index;
2911
3472
    struct resource **r;
2912
3473
 
2913
 
    packet.id = i;
 
3474
    packet.id = terrain_number(pterrain);
 
3475
    packet.native_to = pterrain->native_to;
2914
3476
 
2915
3477
    sz_strlcpy(packet.name_orig, pterrain->name.vernacular);
2916
3478
    sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
2925
3487
 
2926
3488
    packet.num_resources = 0;
2927
3489
    for (r = pterrain->resources; *r; r++) {
2928
 
      packet.resources[packet.num_resources++] = (*r)->index;
 
3490
      packet.resources[packet.num_resources++] = resource_number(*r);
2929
3491
    }
2930
3492
 
2931
3493
    packet.road_trade_incr = pterrain->road_trade_incr;
2932
3494
    packet.road_time = pterrain->road_time;
2933
3495
 
2934
3496
    packet.irrigation_result = (pterrain->irrigation_result
2935
 
                                ? pterrain->irrigation_result->index : -1);
 
3497
                                ? terrain_number(pterrain->irrigation_result)
 
3498
                                : terrain_count());
2936
3499
    packet.irrigation_food_incr = pterrain->irrigation_food_incr;
2937
3500
    packet.irrigation_time = pterrain->irrigation_time;
2938
3501
 
2939
3502
    packet.mining_result = (pterrain->mining_result
2940
 
                            ? pterrain->mining_result->index : -1);
 
3503
                            ? terrain_number(pterrain->mining_result)
 
3504
                            : terrain_count());
2941
3505
    packet.mining_shield_incr = pterrain->mining_shield_incr;
2942
3506
    packet.mining_time = pterrain->mining_time;
2943
3507
 
2944
3508
    packet.transform_result = (pterrain->transform_result
2945
 
                               ? pterrain->transform_result->index : -1);
 
3509
                               ? terrain_number(pterrain->transform_result)
 
3510
                               : terrain_count());
2946
3511
    packet.transform_time = pterrain->transform_time;
2947
3512
    packet.rail_time = pterrain->rail_time;
2948
 
    packet.airbase_time = pterrain->airbase_time;
2949
 
    packet.fortress_time = pterrain->fortress_time;
2950
3513
    packet.clean_pollution_time = pterrain->clean_pollution_time;
2951
3514
    packet.clean_fallout_time = pterrain->clean_fallout_time;
2952
3515
 
2970
3533
  struct packet_ruleset_resource packet;
2971
3534
 
2972
3535
  resource_type_iterate (presource) {
2973
 
    const int i = presource->index;
2974
 
 
2975
 
    packet.id = i;
 
3536
    packet.id = resource_number(presource);
2976
3537
 
2977
3538
    sz_strlcpy(packet.name_orig, presource->name.vernacular);
2978
3539
    sz_strlcpy(packet.graphic_str, presource->graphic_str);
2987
3548
}
2988
3549
 
2989
3550
/**************************************************************************
 
3551
  Send the base ruleset information (all individual base types) to the
 
3552
  specified connections.
 
3553
**************************************************************************/
 
3554
static void send_ruleset_bases(struct conn_list *dest)
 
3555
{
 
3556
  struct packet_ruleset_base packet;
 
3557
 
 
3558
  base_type_iterate(b) {
 
3559
    int j;
 
3560
 
 
3561
    packet.id = base_number(b);
 
3562
    sz_strlcpy(packet.name, b->name.vernacular);
 
3563
    sz_strlcpy(packet.graphic_str, b->graphic_str);
 
3564
    sz_strlcpy(packet.graphic_alt, b->graphic_alt);
 
3565
    sz_strlcpy(packet.activity_gfx, b->activity_gfx);
 
3566
    packet.buildable = b->buildable;
 
3567
    packet.pillageable = b->pillageable;
 
3568
 
 
3569
    j = 0;
 
3570
    requirement_vector_iterate(&b->reqs, preq) {
 
3571
      packet.reqs[j++] = *preq;
 
3572
    } requirement_vector_iterate_end;
 
3573
    packet.reqs_count = j;
 
3574
    packet.native_to = b->native_to;
 
3575
 
 
3576
    packet.gui_type = b->gui_type;
 
3577
    packet.build_time = b->build_time;
 
3578
    packet.defense_bonus = b->defense_bonus;
 
3579
    packet.border_sq = b->border_sq;
 
3580
    packet.vision_main_sq = b->vision_main_sq;
 
3581
    packet.vision_invis_sq = b->vision_invis_sq;
 
3582
 
 
3583
    packet.flags = b->flags;
 
3584
 
 
3585
    lsend_packet_ruleset_base(dest, &packet);
 
3586
  } base_type_iterate_end;
 
3587
}
 
3588
 
 
3589
/**************************************************************************
2990
3590
  Send the government ruleset information to the specified connections.
2991
3591
  One packet per government type, and for each type one per ruler title.
2992
3592
**************************************************************************/
2999
3599
 
3000
3600
  government_iterate(g) {
3001
3601
    /* send one packet_government */
3002
 
    gov.id                 = g->index;
 
3602
    gov.id = government_number(g);
3003
3603
 
3004
3604
    j = 0;
3005
3605
    requirement_vector_iterate(&g->reqs, preq) {
3025
3625
    for(j=0; j<g->num_ruler_titles; j++) {
3026
3626
      p_title = &g->ruler_titles[j];
3027
3627
 
3028
 
      title.gov = g->index;
 
3628
      title.gov = government_number(g);
3029
3629
      title.id = j;
3030
 
      title.nation = p_title->nation ? p_title->nation->index : -1;
 
3630
      title.nation = p_title->nation ? nation_number(p_title->nation) : -1;
3031
3631
      sz_strlcpy(title.male_title, p_title->male.vernacular);
3032
3632
      sz_strlcpy(title.female_title, p_title->female.vernacular);
3033
3633
    
3070
3670
    packet.city_style = n->city_style;
3071
3671
    packet.is_playable = n->is_playable;
3072
3672
    packet.is_available = n->is_available;
3073
 
    packet.is_barbarian = n->is_barbarian;
 
3673
    packet.barbarian_type = n->barb_type;
3074
3674
    memcpy(packet.init_techs, n->init_techs, sizeof(packet.init_techs));
3075
3675
    memcpy(packet.init_buildings, n->init_buildings, 
3076
3676
           sizeof(packet.init_buildings));
3077
3677
    memcpy(packet.init_units, n->init_units, 
3078
3678
           sizeof(packet.init_units));
3079
 
    packet.init_government = n->init_government->index;
 
3679
    packet.init_government = government_number(n->init_government);
3080
3680
 
3081
3681
    sz_strlcpy(packet.legend, n->legend);
3082
3682
 
3112
3712
    sz_strlcpy(city_p.name, city_styles[k].name.vernacular);
3113
3713
    sz_strlcpy(city_p.graphic, city_styles[k].graphic);
3114
3714
    sz_strlcpy(city_p.graphic_alt, city_styles[k].graphic_alt);
 
3715
    sz_strlcpy(city_p.oceanic_graphic, city_styles[k].oceanic_graphic);
 
3716
    sz_strlcpy(city_p.oceanic_graphic_alt, city_styles[k].oceanic_graphic_alt);
3115
3717
    sz_strlcpy(city_p.citizens_graphic, city_styles[k].citizens_graphic);
3116
3718
    sz_strlcpy(city_p.citizens_graphic_alt,
3117
3719
                         city_styles[k].citizens_graphic_alt);
3128
3730
{
3129
3731
  struct packet_ruleset_game misc_p;
3130
3732
 
3131
 
  memcpy(misc_p.trireme_loss_chance, game.trireme_loss_chance, 
3132
 
         sizeof(game.trireme_loss_chance));
3133
3733
  memcpy(misc_p.work_veteran_chance, game.work_veteran_chance, 
3134
3734
         sizeof(game.work_veteran_chance));
3135
3735
  memcpy(misc_p.veteran_chance, game.veteran_chance, 
3136
3736
         sizeof(game.veteran_chance));
3137
3737
    
3138
3738
  assert(sizeof(misc_p.global_init_techs) ==
3139
 
         sizeof(game.rgame.global_init_techs));
 
3739
         sizeof(game.server.rgame.global_init_techs));
3140
3740
  assert(ARRAY_SIZE(misc_p.global_init_techs) ==
3141
 
         ARRAY_SIZE(game.rgame.global_init_techs));
3142
 
  memcpy(misc_p.global_init_techs, game.rgame.global_init_techs,
 
3741
         ARRAY_SIZE(game.server.rgame.global_init_techs));
 
3742
  memcpy(misc_p.global_init_techs, game.server.rgame.global_init_techs,
3143
3743
         sizeof(misc_p.global_init_techs));
3144
3744
 
3145
3745
  misc_p.default_specialist = DEFAULT_SPECIALIST;
3177
3777
 
3178
3778
  freelog(LOG_NORMAL, _("Loading rulesets"));
3179
3779
 
3180
 
  ruleset_data_free();
 
3780
  game_ruleset_free();
 
3781
  game_ruleset_init();
 
3782
 
3181
3783
  reset_player_nations();
3182
 
  game.playable_nations = 0;
 
3784
  server.playable_nations = 0;
3183
3785
 
3184
3786
  openload_ruleset_file(&techfile, "techs");
3185
3787
  load_tech_names(&techfile);
3194
3796
  load_unit_names(&unitfile);
3195
3797
 
3196
3798
  openload_ruleset_file(&terrfile, "terrain");
3197
 
  load_names(&terrfile);
 
3799
  load_terrain_names(&terrfile);
3198
3800
 
3199
3801
  openload_ruleset_file(&cityfile, "cities");
3200
3802
  load_citystyle_names(&cityfile);
3221
3823
 
3222
3824
  precalc_tech_data();
3223
3825
 
 
3826
  if (base_sections) {
 
3827
    free(base_sections);
 
3828
    base_sections = NULL;
 
3829
  }
 
3830
  if (resource_sections) {
 
3831
    free(resource_sections);
 
3832
    resource_sections = NULL;
 
3833
  }
 
3834
  if (terrain_sections) {
 
3835
    free(terrain_sections);
 
3836
    terrain_sections = NULL;
 
3837
  }
 
3838
 
3224
3839
  script_free();
3225
3840
 
3226
3841
  script_init();
 
3842
  openload_script_file("default");
3227
3843
  openload_script_file("script");
3228
3844
 
3229
 
  /* We may need to adjust number of AI players if number of available
3230
 
   * nations changed */
3231
 
  aifill(game.info.aifill);
 
3845
  /* Build AI unit class cache corresponding to loaded rulesets */
 
3846
  unit_class_ai_init();
 
3847
 
 
3848
  /* We may need to adjust the number of AI players
 
3849
   * if the number of available nations changed. */
 
3850
  if (game.info.aifill > server.playable_nations) {
 
3851
    freelog(LOG_NORMAL, _("Reducing aifill because there "
 
3852
                          "are not enough playable nations."));
 
3853
    game.info.aifill = server.playable_nations;
 
3854
    aifill(game.info.aifill);
 
3855
  }
3232
3856
}
3233
3857
 
3234
3858
/**************************************************************************
3243
3867
  send_ruleset_game(dest);
3244
3868
  send_ruleset_techs(dest);
3245
3869
  send_ruleset_governments(dest);
 
3870
  send_ruleset_unit_classes(dest);
3246
3871
  send_ruleset_units(dest);
3247
3872
  send_ruleset_specialists(dest);
3248
3873
  send_ruleset_resources(dest);
3249
3874
  send_ruleset_terrain(dest);
 
3875
  send_ruleset_bases(dest);
3250
3876
  send_ruleset_buildings(dest);
3251
3877
  send_ruleset_nations(dest);
3252
3878
  send_ruleset_cities(dest);
3260
3886
  Does nation have tech initially?
3261
3887
**************************************************************************/
3262
3888
static bool nation_has_initial_tech(struct nation_type *pnation,
3263
 
                                    Tech_type_id tech)
 
3889
                                    struct advance *tech)
3264
3890
{
3265
3891
  int i;
3266
3892
 
3267
3893
  /* See if it's given as global init tech */
3268
 
  for (i = 0;
3269
 
       i < MAX_NUM_TECH_LIST && game.rgame.global_init_techs[i] != A_LAST;
3270
 
       i++) {
3271
 
    if (game.rgame.global_init_techs[i] == tech) {
 
3894
  for (i = 0; i < MAX_NUM_TECH_LIST
 
3895
       && game.server.rgame.global_init_techs[i] != A_LAST; i++) {
 
3896
    if (game.server.rgame.global_init_techs[i] == advance_number(tech)) {
3272
3897
      return TRUE;
3273
3898
    }
3274
3899
  }
3277
3902
  for (i = 0;
3278
3903
       i < MAX_NUM_TECH_LIST && pnation->init_techs[i] != A_LAST;
3279
3904
       i++) {
3280
 
    if (pnation->init_techs[i] == tech) {
 
3905
    if (pnation->init_techs[i] == advance_number(tech)) {
3281
3906
      return TRUE;
3282
3907
    }
3283
3908
  }
3286
3911
}
3287
3912
 
3288
3913
/**************************************************************************
 
3914
  Helper function for sanity_check_req_list() and sanity_check_req_vec()
 
3915
**************************************************************************/
 
3916
static bool sanity_check_req_set(int reqs_of_type[], struct requirement *preq,
 
3917
                                 int max_tiles, const char *list_for)
 
3918
{
 
3919
  int rc;
 
3920
 
 
3921
  assert(preq->source.kind >= 0 && preq->source.kind < VUT_LAST);
 
3922
 
 
3923
  /* Add to counter */
 
3924
  reqs_of_type[preq->source.kind]++;
 
3925
  rc = reqs_of_type[preq->source.kind];
 
3926
 
 
3927
  if (rc > 1) {
 
3928
    /* Multiple requirements of the same type */
 
3929
    switch (preq->source.kind) {
 
3930
     case VUT_GOVERNMENT:
 
3931
     case VUT_NATION:
 
3932
     case VUT_UTYPE:
 
3933
     case VUT_UCLASS:
 
3934
     case VUT_OTYPE:
 
3935
     case VUT_SPECIALIST:
 
3936
     case VUT_MINSIZE: /* Breaks nothing, but has no sense either */
 
3937
     case VUT_MINYEAR:
 
3938
     case VUT_AI_LEVEL:
 
3939
     case VUT_TERRAINCLASS:
 
3940
     case VUT_TERRAINALTER: /* Local range only */
 
3941
     case VUT_CITYTILE:
 
3942
       /* There can be only one requirement of these types (with current
 
3943
        * range limitations)
 
3944
        * Requirements might be identical, but we consider multiple
 
3945
        * declarations error anyway. */
 
3946
 
 
3947
       freelog(LOG_ERROR,
 
3948
               "%s: Requirement list has multiple %s requirements",
 
3949
               list_for,
 
3950
               universal_type_rule_name(&preq->source));
 
3951
       return FALSE;
 
3952
       break;
 
3953
 
 
3954
     case VUT_SPECIAL:
 
3955
     case VUT_TERRAIN:
 
3956
     case VUT_BASE:
 
3957
       /* There can be only up to max_tiles requirements of these types */
 
3958
       if (max_tiles != 1 && rc > max_tiles) {
 
3959
         freelog(LOG_ERROR,
 
3960
                 "%s: Requirement list has more %s requirements than "
 
3961
                 "can ever be fullfilled.",
 
3962
                 list_for,
 
3963
                 universal_type_rule_name(&preq->source));
 
3964
         return FALSE;
 
3965
       }
 
3966
       break;
 
3967
 
 
3968
     case VUT_NONE:
 
3969
     case VUT_ADVANCE:
 
3970
     case VUT_IMPROVEMENT:
 
3971
     case VUT_UTFLAG:
 
3972
     case VUT_UCFLAG:
 
3973
       /* Can have multiple requirements of these types */
 
3974
       break;
 
3975
     case VUT_LAST:
 
3976
       /* Should never be in requirement vector */
 
3977
       assert(FALSE);
 
3978
       return FALSE;
 
3979
       break;
 
3980
       /* No default handling here, as we want compiler warning
 
3981
        * if new requirement type is added to enum and it's not handled
 
3982
        * here. */
 
3983
    }
 
3984
  }
 
3985
 
 
3986
  return TRUE;
 
3987
}
 
3988
 
 
3989
/**************************************************************************
3289
3990
  Check if requirement list is free of conflicting requirements.
3290
3991
  max_tiles is number of tiles that can provide requirement. Value -1
3291
3992
  disables checking based on number of tiles.
3302
4003
                                  int max_tiles,
3303
4004
                                  const char *list_for)
3304
4005
{
3305
 
  int reqs_of_type[REQ_LAST];
 
4006
  int reqs_of_type[VUT_LAST];
3306
4007
 
3307
4008
  /* Initialize requirement counters */
3308
4009
  memset(reqs_of_type, 0, sizeof(reqs_of_type));
3309
4010
 
3310
4011
  requirement_list_iterate(preqs, preq) {
3311
 
    int rc;
3312
 
 
3313
 
    assert(preq->source.type >= 0 && preq->source.type < REQ_LAST);
3314
 
 
3315
 
    /* Add to counter */
3316
 
    reqs_of_type[preq->source.type]++;
3317
 
    rc = reqs_of_type[preq->source.type];
3318
 
 
3319
 
    if (rc > 1) {
3320
 
      /* Multiple requirements of same the type */
3321
 
      switch (preq->source.type) {
3322
 
       case REQ_GOV:
3323
 
       case REQ_NATION:
3324
 
       case REQ_UNITTYPE:
3325
 
       case REQ_UNITCLASS:
3326
 
       case REQ_OUTPUTTYPE:
3327
 
       case REQ_SPECIALIST:
3328
 
       case REQ_MINSIZE: /* Breaks nothing, but has no sense either */
3329
 
         /* There can be only one requirement of these types (with current
3330
 
          * range limitations)
3331
 
          * Requirements might be identical, but we consider multiple
3332
 
          * declarations error anyway. */
3333
 
 
3334
 
         freelog(LOG_ERROR,
3335
 
                 "%s: Requirement list has multiple %s requirements",
3336
 
                 list_for,
3337
 
                 get_req_source_type_name_orig(&preq->source));
3338
 
         return FALSE;
3339
 
         break;
3340
 
 
3341
 
       case REQ_SPECIAL:
3342
 
       case REQ_TERRAIN:
3343
 
         /* There can be only up to max_tiles requirements of these types */
3344
 
         if (max_tiles != 1 && rc > max_tiles) {
3345
 
           freelog(LOG_ERROR,
3346
 
                   "%s: Requirement list has more %s requirements than "
3347
 
                   "can ever be fullfilled.",
3348
 
                   list_for,
3349
 
                   get_req_source_type_name_orig(&preq->source));
3350
 
           return FALSE;
3351
 
         }
3352
 
         break;
3353
 
 
3354
 
       case REQ_NONE:
3355
 
       case REQ_TECH:
3356
 
       case REQ_BUILDING:
3357
 
       case REQ_UNITFLAG:
3358
 
         /* Can have multiple requirements of these types */
3359
 
         break;
3360
 
       case REQ_LAST:
3361
 
         /* Should never be in requirement vector */
3362
 
         assert(FALSE);
3363
 
         return FALSE;
3364
 
         break;
3365
 
       /* No default handling here, as we want compiler warning
3366
 
        * if new requirement type is added to enum and it's not handled
3367
 
        * here. */
3368
 
      }
 
4012
    if (!sanity_check_req_set(reqs_of_type, preq, max_tiles, list_for)) {
 
4013
      return FALSE;
3369
4014
    }
3370
4015
  } requirement_list_iterate_end;
3371
4016
 
3373
4018
}
3374
4019
 
3375
4020
/**************************************************************************
3376
 
  Check that requirement vector and negated requirements vector do not have
 
4021
  Requirement vector version of requirement sanity checking. See
 
4022
  retuirement list version for comments.
 
4023
**************************************************************************/
 
4024
static bool sanity_check_req_vec(const struct requirement_vector *preqs,
 
4025
                                 int max_tiles,
 
4026
                                 const char *list_for)
 
4027
{
 
4028
  int reqs_of_type[VUT_LAST];
 
4029
 
 
4030
  /* Initialize requirement counters */
 
4031
  memset(reqs_of_type, 0, sizeof(reqs_of_type));
 
4032
 
 
4033
  requirement_vector_iterate(preqs, preq) {
 
4034
    if (!sanity_check_req_set(reqs_of_type, preq, max_tiles, list_for)) {
 
4035
      return FALSE;
 
4036
    }
 
4037
  } requirement_vector_iterate_end;
 
4038
 
 
4039
  return TRUE;
 
4040
}
 
4041
 
 
4042
/**************************************************************************
 
4043
  Check that requirement list and negated requirements list do not have
3377
4044
  confliciting requirements.
3378
4045
 
3379
4046
  Returns TRUE iff everything ok.
3397
4064
          freelog(LOG_ERROR,
3398
4065
                  "%s: Identical %s requirement in requirements and negated requirements.",
3399
4066
                  list_for,
3400
 
                  get_req_source_type_name_orig(&preq->source));
 
4067
                  universal_type_rule_name(&preq->source));
3401
4068
          return FALSE;
3402
4069
        }
3403
4070
      } requirement_list_iterate_end;
3410
4077
/**************************************************************************
3411
4078
  Sanity check callback for iterating effects cache.
3412
4079
**************************************************************************/
3413
 
static bool effect_sanity_cb(const struct effect *peffect)
 
4080
static bool effect_list_sanity_cb(const struct effect *peffect)
3414
4081
{
3415
4082
  int one_tile = -1; /* TODO: Determine correct value from effect.
3416
4083
                      *       -1 disables checking */
3429
4096
static bool sanity_check_ruleset_data(void)
3430
4097
{
3431
4098
  int num_utypes;
 
4099
  int i;
 
4100
  bool ok = TRUE; /* Store failures to variable instead of returning
 
4101
                   * immediately so all errors get printed, not just first
 
4102
                   * one. */
3432
4103
 
3433
4104
  /* Check that all players can have their initial techs */
3434
4105
  nations_iterate(pnation) {
3435
4106
    int i;
3436
4107
 
3437
4108
    /* Check global initial techs */
3438
 
    for (i = 0;
3439
 
         i < MAX_NUM_TECH_LIST && game.rgame.global_init_techs[i] != A_LAST;
3440
 
         i++) {
3441
 
      Tech_type_id tech = game.rgame.global_init_techs[i];
3442
 
      if (!tech_exists(tech)) {
3443
 
        freelog(LOG_FATAL, "Tech %s does not exist, but is initial "
3444
 
                           "tech for everyone.",
3445
 
                advance_rule_name(tech));
3446
 
        exit(EXIT_FAILURE);
 
4109
    for (i = 0; i < MAX_NUM_TECH_LIST
 
4110
         && game.server.rgame.global_init_techs[i] != A_LAST; i++) {
 
4111
      Tech_type_id tech = game.server.rgame.global_init_techs[i];
 
4112
      struct advance *a = valid_advance_by_number(tech);
 
4113
 
 
4114
      if (!a) {
 
4115
        ruleset_error(LOG_FATAL,
 
4116
                      "Tech %s does not exist, but is initial "
 
4117
                      "tech for everyone.",
 
4118
                      advance_rule_name(advance_by_number(tech)));
3447
4119
      }
3448
 
      if (advances[tech].root_req != A_NONE
3449
 
          && !nation_has_initial_tech(pnation, advances[tech].root_req)) {
 
4120
      if (advance_by_number(A_NONE) != a->require[AR_ROOT]
 
4121
          && !nation_has_initial_tech(pnation, a->require[AR_ROOT])) {
3450
4122
        /* Nation has no root_req for tech */
3451
 
        freelog(LOG_FATAL, "Tech %s is initial for everyone, but %s has "
3452
 
                           "no root_req for it.",
3453
 
                advance_rule_name(tech),
3454
 
                nation_rule_name(pnation));
3455
 
        exit(EXIT_FAILURE);
 
4123
        ruleset_error(LOG_FATAL,
 
4124
                      "Tech %s is initial for everyone, but %s has "
 
4125
                      "no root_req for it.",
 
4126
                      advance_rule_name(a),
 
4127
                      nation_rule_name(pnation));
3456
4128
      }
3457
4129
    }
3458
4130
 
3461
4133
         i < MAX_NUM_TECH_LIST && pnation->init_techs[i] != A_LAST;
3462
4134
         i++) {
3463
4135
      Tech_type_id tech = pnation->init_techs[i];
3464
 
      if (!tech_exists(tech)) {
3465
 
        freelog(LOG_FATAL, "Tech %s does not exist, but is tech for %s.",
3466
 
                advance_rule_name(tech), nation_rule_name(pnation));
3467
 
        exit(EXIT_FAILURE);
 
4136
      struct advance *a = valid_advance_by_number(tech);
 
4137
 
 
4138
      if (!a) {
 
4139
        ruleset_error(LOG_FATAL,
 
4140
                      "Tech %s does not exist, but is tech for %s.",
 
4141
                      advance_rule_name(advance_by_number(tech)),
 
4142
                      nation_rule_name(pnation));
 
4143
        ok = FALSE;
3468
4144
      }
3469
 
      if (advances[tech].root_req != A_NONE
3470
 
          && !nation_has_initial_tech(pnation, advances[tech].root_req)) {
 
4145
      if (advance_by_number(A_NONE) != a->require[AR_ROOT]
 
4146
          && !nation_has_initial_tech(pnation, a->require[AR_ROOT])) {
3471
4147
        /* Nation has no root_req for tech */
3472
 
        freelog(LOG_FATAL, "Tech %s is initial for %s, but they have "
3473
 
                           "no root_req for it.",
3474
 
                advance_rule_name(tech),
3475
 
                nation_rule_name(pnation));
3476
 
        exit(EXIT_FAILURE);
 
4148
        ruleset_error(LOG_FATAL,
 
4149
                      "Tech %s is initial for %s, but they have "
 
4150
                      "no root_req for it.",
 
4151
                      advance_rule_name(a),
 
4152
                      nation_rule_name(pnation));
 
4153
        ok = FALSE;
3477
4154
      }
3478
4155
    }
3479
4156
  } nations_iterate_end;
3488
4165
      upgraded = upgraded->obsoleted_by;
3489
4166
      chain_length++;
3490
4167
      if (chain_length > num_utypes) {
3491
 
        freelog(LOG_FATAL, "There seems to be obsoleted_by loop in update "
3492
 
                "chain that starts from %s", utype_rule_name(putype));
3493
 
        exit(EXIT_FAILURE);
 
4168
        ruleset_error(LOG_FATAL,
 
4169
                      "There seems to be obsoleted_by loop in update "
 
4170
                      "chain that starts from %s", utype_rule_name(putype));
 
4171
        ok = FALSE;
3494
4172
      }
3495
4173
    }
3496
4174
  } unit_type_iterate_end;
3497
4175
 
3498
 
  /* Check requirement lists against conflicting requirements */
3499
 
  /* Effects */
3500
 
  if (!iterate_effect_cache(effect_sanity_cb)) {
3501
 
    exit(EXIT_FAILURE);
3502
 
  }
3503
 
  /* TODO: Check other requirement lists also
3504
 
   *       (Governments, Buildings, Specialists, City styles)
3505
 
   *       These use currently requirement_vector, when effects
3506
 
   *       (and sanity checking) use requirement_list. */
3507
 
 
3508
 
  return TRUE;
 
4176
  /* Check requirement sets against conflicting requirements.
 
4177
   * Effects use requirement lists */
 
4178
  if (!iterate_effect_cache(effect_list_sanity_cb)) {
 
4179
    ruleset_error(LOG_FATAL, "Effects have conflicting requirements!");
 
4180
    ok = FALSE;
 
4181
  }
 
4182
 
 
4183
  /* Others use requirement vectors
 
4184
   * Buildings */
 
4185
  improvement_iterate(pimprove) {
 
4186
    if (!sanity_check_req_vec(&pimprove->reqs, -1,
 
4187
                              improvement_rule_name(pimprove))) {
 
4188
      ruleset_error(LOG_FATAL, "Buildings have conflicting requirements!");
 
4189
      ok = FALSE;
 
4190
    }
 
4191
  } improvement_iterate_end;
 
4192
 
 
4193
  /* Governments */
 
4194
  government_iterate(pgov) {
 
4195
    if (!sanity_check_req_vec(&pgov->reqs, -1,
 
4196
                              government_rule_name(pgov))) {
 
4197
      ruleset_error(LOG_FATAL, "Governments have conflicting requirements!");
 
4198
      ok = FALSE;
 
4199
    }
 
4200
  } government_iterate_end;
 
4201
 
 
4202
  /* Specialists */
 
4203
  specialist_type_iterate(sp) {
 
4204
    struct specialist *psp = specialist_by_number(sp);
 
4205
 
 
4206
    if (!sanity_check_req_vec(&psp->reqs, -1,
 
4207
                              specialist_rule_name(psp))) {
 
4208
      ruleset_error(LOG_FATAL, "Specialists have conflicting requirements!");
 
4209
      ok = FALSE;
 
4210
    }
 
4211
  } specialist_type_iterate_end;
 
4212
 
 
4213
  /* City styles */
 
4214
  for (i = 0; i < game.control.styles_count; i++) {
 
4215
    if (!sanity_check_req_vec(&city_styles[i].reqs, -1,
 
4216
                              city_style_rule_name(i))) {
 
4217
      ruleset_error(LOG_FATAL, "City styles have conflicting requirements!");
 
4218
      ok = FALSE;
 
4219
    }
 
4220
  }
 
4221
 
 
4222
  return ok;
3509
4223
}