79
89
/**************************************************************************
80
Parse a requirement type and value string into a requirement source
81
structure. Passing in a NULL type is considered REQ_NONE (not an error).
90
Parse requirement type (kind) and value strings into a universal
91
structure. Passing in a NULL type is considered VUT_NONE (not an error).
83
93
Pass this some values like "Building", "Factory".
94
FIXME: ensure that every caller checks error return!
84
95
**************************************************************************/
85
struct req_source req_source_from_str(const char *type, const char *value)
96
struct universal universal_by_rule_name(const char *kind,
87
struct req_source source;
89
assert(ARRAY_SIZE(req_source_type_names) == REQ_LAST);
92
source.type < ARRAY_SIZE(req_source_type_names);
94
if (0 == mystrcasecmp(req_source_type_names[source.type], type)) {
99
struct universal source = { .kind = VUT_LAST };
101
RETURN_VAL_IF_FAIL(ARRAY_SIZE(universal_names) == VUT_LAST, source);
104
for (source.kind = 0;
105
source.kind < ARRAY_SIZE(universal_names);
107
if (0 == mystrcasecmp(universal_names[source.kind], kind)) {
99
source.type = REQ_NONE;
112
source.kind = VUT_NONE;
102
115
/* Finally scan the value string based on the type of the source. */
103
switch (source.type) {
116
switch (source.kind) {
107
source.value.tech = find_advance_by_rule_name(value);
108
if (source.value.tech != A_LAST) {
113
source.value.gov = find_government_by_rule_name(value);
114
if (source.value.gov != NULL) {
120
source.value.advance = find_advance_by_rule_name(value);
121
if (source.value.advance != NULL) {
126
source.value.govern = find_government_by_rule_name(value);
127
if (source.value.govern != NULL) {
131
case VUT_IMPROVEMENT:
119
132
source.value.building = find_improvement_by_rule_name(value);
120
if (source.value.building != B_LAST) {
133
if (source.value.building != NULL) {
125
138
source.value.special = find_special_by_rule_name(value);
126
139
if (source.value.special != S_LAST) {
131
144
source.value.terrain = find_terrain_by_rule_name(value);
132
145
if (source.value.terrain != T_UNKNOWN) {
137
150
source.value.nation = find_nation_by_rule_name(value);
138
151
if (source.value.nation != NO_NATION_SELECTED) {
143
source.value.unittype = find_unit_type_by_rule_name(value);
144
if (source.value.unittype) {
156
source.value.utype = find_unit_type_by_rule_name(value);
157
if (source.value.utype) {
149
162
source.value.unitflag = find_unit_flag_by_rule_name(value);
150
163
if (source.value.unitflag != F_LAST) {
155
source.value.unitclass = find_unit_class_by_rule_name(value);
156
if (source.value.unitclass) {
168
source.value.uclass = find_unit_class_by_rule_name(value);
169
if (source.value.uclass) {
174
source.value.unitclassflag = find_unit_class_flag_by_rule_name(value);
175
if (source.value.unitclassflag != UCF_LAST) {
161
180
source.value.outputtype = find_output_type_by_identifier(value);
162
181
if (source.value.outputtype != O_LAST) {
167
source.value.specialist = find_specialist_by_name(value);
168
if (source.value.specialist != SP_MAX) {
186
source.value.specialist = find_specialist_by_rule_name(value);
187
if (source.value.specialist) {
172
191
source.value.minsize = atoi(value);
173
192
if (source.value.minsize > 0) {
197
source.value.ai_level = find_ai_level_by_name(value);
198
if (source.value.ai_level != AI_LEVEL_LAST) {
202
case VUT_TERRAINCLASS:
203
source.value.terrainclass = find_terrain_class_by_rule_name(value);
204
if (source.value.terrainclass != TC_LAST) {
209
source.value.base = find_base_type_by_rule_name(value);
210
if (source.value.base != NULL) {
215
source.value.minyear = atoi(value);
216
if (source.value.minyear >= GAME_START_YEAR) {
220
case VUT_TERRAINALTER:
221
source.value.terrainalter = find_terrain_alteration_by_rule_name(value);
222
if (source.value.terrainalter != TA_LAST) {
227
source.value.citytile = find_citytile_by_rule_name(value);
228
if (source.value.citytile != CITYT_LAST) {
181
236
/* If we reach here there's been an error. */
182
source.type = REQ_LAST;
237
source.kind = VUT_LAST;
186
241
/**************************************************************************
187
Parse some integer values into a req source. This is for serialization
188
of req sources and is the opposite of req_source_get_values().
242
Combine values into a universal structure. This is for serialization
243
and is the opposite of universal_extraction().
244
FIXME: ensure that every caller checks error return!
189
245
**************************************************************************/
190
struct req_source req_source_from_values(int type, int value)
246
struct universal universal_by_number(const enum universals_n kind,
192
struct req_source source;
196
switch (source.type) {
200
source.value.tech = value;
203
source.value.gov = government_by_number(value);
206
source.value.building = value;
249
struct universal source;
253
switch (source.kind) {
257
source.value.advance = advance_by_number(value);
258
if (source.value.advance != NULL) {
263
source.value.govern = government_by_number(value);
264
if (source.value.govern != NULL) {
268
case VUT_IMPROVEMENT:
269
source.value.building = improvement_by_number(value);
270
if (source.value.building != NULL) {
209
275
source.value.special = value;
212
278
source.value.terrain = terrain_by_number(value);
279
if (source.value.terrain != NULL) {
215
284
source.value.nation = nation_by_number(value);
218
source.value.unittype = utype_by_number(value);
285
if (source.value.nation != NULL) {
290
source.value.utype = utype_by_number(value);
291
if (source.value.utype != NULL) {
221
296
source.value.unitflag = value;
224
source.value.unitclass = uclass_by_number(value);
299
source.value.uclass = uclass_by_number(value);
300
if (source.value.uclass != NULL) {
305
source.value.unitclassflag = value;
227
308
source.value.outputtype = value;
230
source.value.specialist = value;
311
source.value.specialist = specialist_by_number(value);
233
314
source.value.minsize = value;
317
source.value.ai_level = value;
319
case VUT_TERRAINCLASS:
320
source.value.terrainclass = value;
323
source.value.base = base_by_number(value);
326
source.value.minyear = value;
328
case VUT_TERRAINALTER:
329
source.value.terrainalter = value;
332
source.value.citytile = value;
239
source.type = REQ_LAST;
338
/* If we reach here there's been an error. */
339
source.kind = VUT_LAST;
244
343
/**************************************************************************
245
Look at a req source and return some integer values describing it. This
246
is for serialization of req sources and is the opposite of
247
req_source_from_values().
344
Extract universal structure into its components for serialization;
345
the opposite of universal_by_number().
248
346
**************************************************************************/
249
void req_source_get_values(const struct req_source *source,
250
int *type, int *value)
347
void universal_extraction(const struct universal *source,
348
int *kind, int *value)
252
*type = source->type;
350
*kind = source->kind;
351
*value = universal_number(source);
254
switch (source->type) {
259
*value = source->value.tech;
262
*value = source->value.gov->index;
265
*value = source->value.building;
268
*value = source->value.special;
271
*value = source->value.terrain->index;
274
*value = nation_number(source->value.nation);
277
*value = source->value.unittype->index;
280
*value = source->value.unitflag;
283
*value = source->value.unitclass->id;
286
*value = source->value.outputtype;
289
*value = source->value.specialist;
292
*value = source->value.minsize;
354
/**************************************************************************
355
Return the universal number of the constituent.
356
**************************************************************************/
357
int universal_number(const struct universal *source)
359
switch (source->kind) {
363
return advance_number(source->value.advance);
365
return government_number(source->value.govern);
366
case VUT_IMPROVEMENT:
367
return improvement_number(source->value.building);
369
return source->value.special;
371
return terrain_number(source->value.terrain);
373
return nation_number(source->value.nation);
375
return utype_number(source->value.utype);
377
return source->value.unitflag;
379
return uclass_number(source->value.uclass);
381
return source->value.unitclassflag;
383
return source->value.outputtype;
385
return specialist_number(source->value.specialist);
387
return source->value.minsize;
389
return source->value.ai_level;
390
case VUT_TERRAINCLASS:
391
return source->value.terrainclass;
393
return base_number(source->value.base);
395
return source->value.minyear;
396
case VUT_TERRAINALTER:
397
return source->value.terrainalter;
399
return source->value.citytile;
404
/* If we reach here there's been an error. */
405
freelog(LOG_ERROR, "universal_number(): invalid source kind %d.",
302
410
/****************************************************************************
303
411
Parse a requirement type and value string into a requrement structure.
304
Returns REQ_LAST on error. Passing in a NULL type is considered REQ_NONE
412
Returns VUT_LAST on error. Passing in a NULL type is considered VUT_NONE
307
415
Pass this some values like "Building", "Factory".
807
freelog(LOG_ERROR, "is_terrain_in_range(): invalid range %d.", range);
811
/****************************************************************************
812
Is there a source terrain class within range of the target?
813
****************************************************************************/
814
static bool is_terrain_class_in_range(const struct tile *target_tile,
815
enum req_range range, bool survives,
816
enum terrain_class class)
823
case REQ_RANGE_LOCAL:
824
/* The requirement is filled if the tile has the terrain of correct class. */
825
return terrain_belongs_to_class(tile_terrain(target_tile), class);
826
case REQ_RANGE_ADJACENT:
827
return is_terrain_class_near_tile(target_tile, class);
829
case REQ_RANGE_CONTINENT:
830
case REQ_RANGE_PLAYER:
831
case REQ_RANGE_WORLD:
836
freelog(LOG_ERROR, "is_terrain_class_in_range(): invalid range %d.",
841
/****************************************************************************
842
Is there a source base type within range of the target?
843
****************************************************************************/
844
static bool is_base_type_in_range(const struct tile *target_tile,
845
enum req_range range, bool survives,
846
struct base_type *pbase)
853
case REQ_RANGE_LOCAL:
854
/* The requirement is filled if the tile has base of requested type. */
855
return tile_has_base(target_tile, pbase);
856
case REQ_RANGE_ADJACENT:
857
return is_base_near_tile(target_tile, pbase);
859
case REQ_RANGE_CONTINENT:
860
case REQ_RANGE_PLAYER:
861
case REQ_RANGE_WORLD:
866
freelog(LOG_ERROR, "is_base_type_in_range(): invalid range %d.", range);
870
/****************************************************************************
871
Is there a terrain which can support the specified infrastructure
872
within range of the target?
873
****************************************************************************/
874
static bool is_terrain_alter_possible_in_range(const struct tile *target_tile,
875
enum req_range range, bool survives,
876
enum terrain_alteration alteration)
883
case REQ_RANGE_LOCAL:
884
return terrain_can_support_alteration(tile_terrain(target_tile),
886
case REQ_RANGE_ADJACENT: /* XXX Could in principle support ADJACENT. */
888
case REQ_RANGE_CONTINENT:
889
case REQ_RANGE_PLAYER:
890
case REQ_RANGE_WORLD:
896
"is_terrain_alter_possible_in_range(): invalid range %d.", range);
829
1046
req->range, req->survives,
830
1047
req->source.value.building) > 0);
833
1050
eval = is_special_in_range(target_tile,
834
1051
req->range, req->survives,
835
1052
req->source.value.special);
838
1055
eval = is_terrain_in_range(target_tile,
839
1056
req->range, req->survives,
840
1057
req->source.value.terrain);
843
1060
eval = is_nation_in_range(target_player, req->range, req->survives,
844
1061
req->source.value.nation);
847
1064
eval = is_unittype_in_range(target_unittype,
848
1065
req->range, req->survives,
849
req->source.value.unittype);
1066
req->source.value.utype);
852
1069
eval = is_unitflag_in_range(target_unittype,
853
1070
req->range, req->survives,
854
1071
req->source.value.unitflag,
858
1075
eval = is_unitclass_in_range(target_unittype,
859
1076
req->range, req->survives,
860
req->source.value.unitclass);
1077
req->source.value.uclass);
1080
eval = is_unitclassflag_in_range(target_unittype,
1081
req->range, req->survives,
1082
req->source.value.unitclassflag);
863
1085
eval = (target_output
864
1086
&& target_output->index == req->source.value.outputtype);
1088
case VUT_SPECIALIST:
867
1089
eval = (target_specialist
868
&& target_specialist->index == req->source.value.specialist);
1090
&& target_specialist == req->source.value.specialist);
871
1093
eval = target_city && target_city->size >= req->source.value.minsize;
1096
eval = target_player
1097
&& target_player->ai_data.control
1098
&& target_player->ai_data.skill_level == req->source.value.ai_level;
1100
case VUT_TERRAINCLASS:
1101
eval = is_terrain_class_in_range(target_tile,
1102
req->range, req->survives,
1103
req->source.value.terrainclass);
1106
eval = is_base_type_in_range(target_tile,
1107
req->range, req->survives,
1108
req->source.value.base);
1111
eval = game.info.year >= req->source.value.minyear;
1113
case VUT_TERRAINALTER:
1114
eval = is_terrain_alter_possible_in_range(target_tile,
1115
req->range, req->survives,
1116
req->source.value.terrainalter);
1120
if (req->source.value.citytile == CITYT_CENTER) {
1122
eval = is_city_center(target_city, target_tile);
1124
eval = tile_city(target_tile) != NULL;
1127
/* Not implemented */
1128
freelog(LOG_ERROR, "is_req_active(): citytile %d not supported.",
1129
req->source.value.citytile);
1137
freelog(LOG_ERROR, "is_req_active(): invalid source kind %d.",
960
1234
Return TRUE iff the two sources are equivalent. Note this isn't the
961
1235
same as an == or memcmp check.
962
1236
*****************************************************************************/
963
bool are_req_sources_equal(const struct req_source *psource1,
964
const struct req_source *psource2)
1237
bool are_universals_equal(const struct universal *psource1,
1238
const struct universal *psource2)
966
if (psource1->type != psource2->type) {
1240
if (psource1->kind != psource2->kind) {
969
switch (psource1->type) {
1243
switch (psource1->kind) {
973
return psource1->value.tech == psource2->value.tech;
975
return psource1->value.gov == psource2->value.gov;
1247
return psource1->value.advance == psource2->value.advance;
1248
case VUT_GOVERNMENT:
1249
return psource1->value.govern == psource2->value.govern;
1250
case VUT_IMPROVEMENT:
977
1251
return psource1->value.building == psource2->value.building;
979
1253
return psource1->value.special == psource2->value.special;
981
1255
return psource1->value.terrain == psource2->value.terrain;
983
1257
return psource1->value.nation == psource2->value.nation;
985
return psource1->value.unittype == psource2->value.unittype;
1259
return psource1->value.utype == psource2->value.utype;
987
1261
return psource1->value.unitflag == psource2->value.unitflag;
989
return psource1->value.unitclass == psource2->value.unitclass;
1263
return psource1->value.uclass == psource2->value.uclass;
1265
return psource1->value.unitclassflag == psource2->value.unitclassflag;
991
1267
return psource1->value.outputtype == psource2->value.outputtype;
1268
case VUT_SPECIALIST:
993
1269
return psource1->value.specialist == psource2->value.specialist;
995
1271
return psource1->value.minsize == psource2->value.minsize;
1273
return psource1->value.ai_level == psource2->value.ai_level;
1274
case VUT_TERRAINCLASS:
1275
return psource1->value.terrainclass == psource2->value.terrainclass;
1277
return psource1->value.base == psource2->value.base;
1279
return psource1->value.minyear == psource2->value.minyear;
1280
case VUT_TERRAINALTER:
1281
return psource1->value.terrainalter == psource2->value.terrainalter;
1283
return psource1->value.citytile == psource2->value.citytile;
1287
freelog(LOG_ERROR, "are_universals_equal(): invalid source kind %d.",
1003
1292
/****************************************************************************
1293
Return the (untranslated) rule name of the kind of universal.
1294
You don't have to free the return pointer.
1295
*****************************************************************************/
1296
const char *universal_kind_name(const enum universals_n kind)
1298
RETURN_VAL_IF_FAIL(kind >= 0 && kind < ARRAY_SIZE(universal_names), NULL);
1299
return universal_names[kind];
1302
/****************************************************************************
1303
Return the (untranslated) rule name of the universal.
1304
You don't have to free the return pointer.
1305
*****************************************************************************/
1306
const char *universal_rule_name(const struct universal *psource)
1308
switch (psource->kind) {
1312
/* TRANS: missing value */
1313
return N_("(none)");
1315
return advance_rule_name(psource->value.advance);
1316
case VUT_GOVERNMENT:
1317
return government_rule_name(psource->value.govern);
1318
case VUT_IMPROVEMENT:
1319
return improvement_rule_name(psource->value.building);
1321
return special_rule_name(psource->value.special);
1323
return terrain_rule_name(psource->value.terrain);
1325
return nation_rule_name(psource->value.nation);
1327
return utype_rule_name(psource->value.utype);
1329
return unit_flag_rule_name(psource->value.unitflag);
1331
return uclass_rule_name(psource->value.uclass);
1333
return unit_class_flag_rule_name(psource->value.unitclassflag);
1335
return get_output_name(psource->value.outputtype);
1336
case VUT_SPECIALIST:
1337
return specialist_rule_name(psource->value.specialist);
1339
return N_("Size %d");
1341
return ai_level_name(psource->value.ai_level);
1342
case VUT_TERRAINCLASS:
1343
return terrain_class_rule_name(psource->value.terrainclass);
1345
return base_rule_name(psource->value.base);
1346
case VUT_TERRAINALTER:
1347
return terrain_alteration_rule_name(psource->value.terrainalter);
1352
freelog(LOG_ERROR, "universal_rule_name: invalid source kind %d.",
1357
/****************************************************************************
1004
1358
Make user-friendly text for the source. The text is put into a user
1005
1359
buffer which is also returned.
1006
1360
*****************************************************************************/
1007
char *get_req_source_text(const struct req_source *psource,
1008
char *buf, size_t bufsz)
1361
const char *universal_name_translation(const struct universal *psource,
1362
char *buf, size_t bufsz)
1010
1364
buf[0] = '\0'; /* to be safe. */
1011
switch (psource->type) {
1365
switch (psource->kind) {
1013
1367
/* TRANS: missing value */
1014
1368
mystrlcat(buf, _("(none)"), bufsz);
1017
mystrlcat(buf, advance_name_translation(psource->value.tech), bufsz);
1020
mystrlcat(buf, government_name_translation(psource->value.gov), bufsz);
1371
mystrlcat(buf, advance_name_translation(psource->value.advance), bufsz);
1373
case VUT_GOVERNMENT:
1374
mystrlcat(buf, government_name_translation(psource->value.govern), bufsz);
1376
case VUT_IMPROVEMENT:
1023
1377
mystrlcat(buf, improvement_name_translation(psource->value.building), bufsz);
1026
1380
mystrlcat(buf, special_name_translation(psource->value.special), bufsz);
1029
1383
mystrlcat(buf, terrain_name_translation(psource->value.terrain), bufsz);
1032
1386
mystrlcat(buf, nation_adjective_translation(psource->value.nation), bufsz);
1035
mystrlcat(buf, utype_name_translation(psource->value.unittype), bufsz);
1038
cat_snprintf(buf, bufsz, _("%s units"),
1389
mystrlcat(buf, utype_name_translation(psource->value.utype), bufsz);
1392
cat_snprintf(buf, bufsz, _("\"%s\" units"),
1393
/* flag names are never translated */
1039
1394
unit_flag_rule_name(psource->value.unitflag));
1042
1397
cat_snprintf(buf, bufsz, _("%s units"),
1043
uclass_name_translation(psource->value.unitclass));
1045
case REQ_OUTPUTTYPE:
1046
mystrlcat(buf, get_output_name(psource->value.outputtype), bufsz);
1048
case REQ_SPECIALIST:
1049
mystrlcat(buf, get_specialist(psource->value.specialist)->name, bufsz);
1398
uclass_name_translation(psource->value.uclass));
1401
cat_snprintf(buf, bufsz, _("\"%s\" units"),
1402
/* flag names are never translated */
1403
unit_class_flag_rule_name(psource->value.unitclassflag));
1406
mystrlcat(buf, get_output_name(psource->value.outputtype), bufsz); /* FIXME */
1408
case VUT_SPECIALIST:
1409
mystrlcat(buf, specialist_name_translation(psource->value.specialist), bufsz);
1052
1412
cat_snprintf(buf, bufsz, _("Size %d"),
1053
1413
psource->value.minsize);
1416
/* TRANS: "Hard AI" */
1417
cat_snprintf(buf, bufsz, _("%s AI"),
1418
ai_level_name(psource->value.ai_level)); /* FIXME */
1420
case VUT_TERRAINCLASS:
1421
/* TRANS: "Land terrain" */
1422
cat_snprintf(buf, bufsz, _("%s terrain"),
1423
terrain_class_name_translation(psource->value.terrainclass));
1426
/* TRANS: "Fortress base" */
1427
cat_snprintf(buf, bufsz, _("%s base"),
1428
base_name_translation(psource->value.base));
1431
cat_snprintf(buf, bufsz, _("After %s"),
1432
textyear(psource->value.minyear));
1434
case VUT_TERRAINALTER:
1435
/* TRANS: "Irrigation possible" */
1436
cat_snprintf(buf, bufsz, _("%s possible"),
1437
terrain_alteration_name_translation(psource->value.terrainalter));
1440
mystrlcat(buf, _("City center tile"), bufsz);
1446
freelog(LOG_ERROR, "universal_rule_name: invalid source kind %d.",
1064
1452
/****************************************************************************
1065
Return untranslated name of the requirement source name.
1453
Return untranslated name of the universal source name.
1066
1454
*****************************************************************************/
1067
const char *get_req_source_type_name_orig(const struct req_source *psource)
1069
return req_source_type_names[psource->type];
1455
const char *universal_type_rule_name(const struct universal *psource)
1457
return universal_kind_name(psource->kind);
1460
/**************************************************************************
1461
Return the number of shields it takes to build this universal.
1462
**************************************************************************/
1463
int universal_build_shield_cost(const struct universal *target)
1465
switch (target->kind) {
1466
case VUT_IMPROVEMENT:
1467
return impr_build_shield_cost(target->value.building);
1469
return utype_build_shield_cost(target->value.utype);