Freeciv-3.3: /fast/freeciv/nightly/main/server/ruleset/rssanity.c Source File

Freeciv-3.3

Loading...
Searching...
No Matches
rssanity.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "astring.h"
20#include "deprecations.h"
21
22/* common */
23#include "achievements.h"
24#include "actions.h"
25#include "effects.h"
26#include "game.h"
27#include "government.h"
28#include "map.h"
29#include "movement.h"
30#include "nation.h"
31#include "player.h"
32#include "specialist.h"
33#include "tech.h"
34
35/* server */
36#include "ruleload.h"
37#include "settings.h"
38
39#include "rssanity.h"
40
41/* These effects are always needed in the ruleset.
42 * First set are those that are mandatory even in compatibility mode. */
43 enum effect_type req_base_effects[] =
44 {
45 EFT_CITY_VISION_RADIUS_SQ,
46 EFT_MAX_RATES,
47 EFT_COUNT
48 };
49
50/* These have been made mandatory in freeciv-3.3 */
51 enum effect_type req_base_effects_3_3[] =
52 {
53 /* None yet */
54 EFT_COUNT
55 };
56
57/**********************************************************************/
60 static bool sanity_check_metadata(rs_conversion_logger logger)
61{
62 if (game.ruleset_summary != NULL
63 && strlen(game.ruleset_summary) > MAX_LEN_CONTENT) {
64 ruleset_error(logger,
65 LOG_ERROR,
66 _("Too long ruleset summary. It can be only %d bytes long. "
67 "Put longer explanations to ruleset description."),
68 MAX_LEN_CONTENT);
69 return FALSE;
70 }
71
72 return TRUE;
73}
74
75/**********************************************************************/
78 static bool nation_has_initial_tech(struct nation_type *pnation,
79 struct advance *tech)
80{
81 int i;
82
83 /* See if it's given as global init tech */
84 for (i = 0; i < MAX_NUM_TECH_LIST
85 && game.rgame.global_init_techs[i] != A_LAST; i++) {
86 if (game.rgame.global_init_techs[i] == advance_number(tech)) {
87 return TRUE;
88 }
89 }
90
91 /* See if it's given as national init tech */
92 for (i = 0;
93 i < MAX_NUM_TECH_LIST && pnation->init_techs[i] != A_LAST;
94 i++) {
95 if (pnation->init_techs[i] == advance_number(tech)) {
96 return TRUE;
97 }
98 }
99
100 return FALSE;
101}
102
103/**********************************************************************/
107 static bool sanity_check_setting_is_seen(struct setting *pset)
108{
109 return setting_is_visible_at_level(pset, ALLOW_INFO);
110}
111
112/**********************************************************************/
116 static bool sanity_check_setting_is_game_rule(struct setting *pset)
117{
118 if ((setting_category(pset) == SSET_INTERNAL
119 || setting_category(pset) == SSET_NETWORK)
120 /* White list for SSET_INTERNAL and SSET_NETWORK settings. */
121 && !(pset == setting_by_name("phasemode")
122 || pset == setting_by_name("timeout")
123 || pset == setting_by_name("timeaddenemymove")
124 || pset == setting_by_name("unitwaittime")
125 || pset == setting_by_name("victories"))) {
126 /* The given server setting is a server operator related setting (like
127 * the compression type of savegames), not a game rule. */
128 return FALSE;
129 }
130
131 if (pset == setting_by_name("naturalcitynames")) {
132 /* This setting is about "look", not rules. */
133 return FALSE;
134 }
135
136 return TRUE;
137}
138
139/**********************************************************************/
143 bool sanity_check_server_setting_value_in_req(ssetv ssetval)
144{
145 server_setting_id id;
146 struct setting *pset;
147
148 /* TODO: use ssetv_setting_get() if setting value becomes multiplexed with
149 * the server setting id. */
150 id = (server_setting_id)ssetval;
151 fc_assert_ret_val(server_setting_exists(id), FALSE);
152
153 if (server_setting_type_get(id) != SST_BOOL) {
154 /* Not supported yet. */
155 return FALSE;
156 }
157
158 pset = setting_by_number(id);
159
160 return (sanity_check_setting_is_seen(pset)
161 && sanity_check_setting_is_game_rule(pset));
162}
163
164/**********************************************************************/
170 static bool sanity_check_req_individual(rs_conversion_logger logger,
171 struct requirement *preq,
172 const char *list_for)
173{
174 switch (preq->source.kind) {
175 case VUT_IMPROVEMENT:
176 /* This check corresponds to what is_req_active() will support.
177 * It can't be done in req_from_str(), as we may not have
178 * loaded all building information at that time. */
179 {
180 const struct impr_type *pimprove = preq->source.value.building;
181
182 if (preq->range == REQ_RANGE_WORLD && !is_great_wonder(pimprove)) {
183 ruleset_error(logger, LOG_ERROR,
184 _("%s: World-ranged requirement not supported for "
185 "%s (only great wonders supported)"), list_for,
186 improvement_name_translation(pimprove));
187 return FALSE;
188 } else if (preq->range > REQ_RANGE_TRADE_ROUTE && !is_wonder(pimprove)) {
189 ruleset_error(logger, LOG_ERROR,
190 _("%s: %s-ranged requirement not supported for "
191 "%s (only wonders supported)"), list_for,
192 req_range_name(preq->range),
193 improvement_name_translation(pimprove));
194 return FALSE;
195 }
196 }
197 break;
198 case VUT_MINCALFRAG:
199 /* Currently [calendar] is loaded after some requirements are
200 * parsed, so we can't do this in universal_value_from_str(). */
201 if (game.calendar.calendar_fragments < 1) {
202 ruleset_error(logger, LOG_ERROR,
203 _("%s: MinCalFrag requirement used in ruleset without "
204 "calendar fragments"), list_for);
205 return FALSE;
206 } else if (preq->source.value.mincalfrag >= game.calendar.calendar_fragments) {
207 ruleset_error(logger, LOG_ERROR,
208 _("%s: MinCalFrag requirement %d out of range (max %d in "
209 "this ruleset)"), list_for, preq->source.value.mincalfrag,
210 game.calendar.calendar_fragments-1);
211 return FALSE;
212 }
213 break;
214 case VUT_SERVERSETTING:
215 /* There is currently no way to check a server setting's category and
216 * access level that works in both the client and the server. */
217 {
218 server_setting_id id;
219 struct setting *pset;
220
221 id = ssetv_setting_get(preq->source.value.ssetval);
222 fc_assert_ret_val(server_setting_exists(id), FALSE);
223 pset = setting_by_number(id);
224
225 if (!sanity_check_setting_is_seen(pset)) {
226 ruleset_error(logger, LOG_ERROR,
227 _("%s: ServerSetting requirement %s isn't visible enough "
228 "to appear in a requirement. Everyone should be able to "
229 "see the value of a server setting that appears in a "
230 "requirement."), list_for, server_setting_name_get(id));
231 return FALSE;
232 }
233
234 if (!sanity_check_setting_is_game_rule(pset)) {
235 /* This is a server operator related setting (like the compression
236 * type of savegames), not a game rule. */
237 ruleset_error(logger, LOG_ERROR,
238 _("%s: ServerSetting requirement setting %s isn't about a "
239 "game rule."),
240 list_for, server_setting_name_get(id));
241 return FALSE;
242 }
243 }
244 break;
245 default:
246 /* No other universals have checks that can't be done at ruleset
247 * load time. See req_from_str(). */
248 break;
249 }
250 return TRUE;
251}
252
253/**********************************************************************/
256 static bool sanity_check_req_set(rs_conversion_logger logger,
257 int reqs_of_type[],
258 int local_reqs_of_type[],
259 int tile_reqs_of_type[],
260 struct requirement *preq, bool conjunctive,
261 int max_tiles, const char *list_for)
262{
263 int rc;
264
265 fc_assert_ret_val(universals_n_is_valid(preq->source.kind), FALSE);
266
267 if (!sanity_check_req_individual(logger, preq, list_for)) {
268 return FALSE;
269 }
270
271 if (!conjunctive) {
272 /* All the checks below are only meaningful for conjunctive lists. */
273 /* FIXME: we could add checks suitable for disjunctive lists. */
274 return TRUE;
275 }
276
277 /* Add to counter for positive requirements. */
278 if (preq->present) {
279 reqs_of_type[preq->source.kind]++;
280 }
281 rc = reqs_of_type[preq->source.kind];
282
283 if (preq->range == REQ_RANGE_LOCAL && preq->present) {
284 local_reqs_of_type[preq->source.kind]++;
285
286 switch (preq->source.kind) {
287 case VUT_EXTRA:
288 if (local_reqs_of_type[VUT_EXTRA] > 1) {
289 ruleset_error(logger, LOG_ERROR,
290 _("%s: Requirement list has multiple local-ranged extra "
291 "requirements (did you mean to make them tile-ranged?)"),
292 list_for);
293 return FALSE;
294 }
295 break;
296 default:
297 break;
298 }
299 }
300
301 if (preq->range == REQ_RANGE_TILE && preq->present) {
302 tile_reqs_of_type[preq->source.kind]++;
303
304 switch (preq->source.kind) {
305 case VUT_TERRAINCLASS:
306 if (tile_reqs_of_type[VUT_TERRAIN] > 0) {
307 ruleset_error(logger, LOG_ERROR,
308 _("%s: Requirement list has both tile terrain and terrainclass requirement"),
309 list_for);
310 return FALSE;
311 }
312 break;
313 case VUT_TERRAIN:
314 if (tile_reqs_of_type[VUT_TERRAINCLASS] > 0) {
315 ruleset_error(logger, LOG_ERROR,
316 _("%s: Requirement list has both tile terrain and terrainclass requirement"),
317 list_for);
318 return FALSE;
319 }
320 break;
321 case VUT_MINLATITUDE:
322 case VUT_MAXLATITUDE:
323 if (tile_reqs_of_type[preq->range] > 1) {
324 ruleset_error(logger, LOG_ERROR,
325 _("%s: Requirement list has duplicate %s requirement at Tile range"),
326 list_for, universal_type_rule_name(&preq->source));
327 return FALSE;
328 }
329 break;
330 default:
331 break;
332 }
333 }
334
335 if (rc > 1 && preq->present) {
336 /* Multiple requirements of the same type */
337 switch (preq->source.kind) {
338 case VUT_GOVERNMENT:
339 case VUT_ACTION:
340 case VUT_ACTIVITY:
341 case VUT_OTYPE:
342 case VUT_SPECIALIST:
343 case VUT_MINSIZE: /* Breaks nothing, but has no sense either */
344 case VUT_MINCITIES:
345 case VUT_MINFOREIGNPCT:
346 case VUT_MINMOVES: /* Breaks nothing, but has no sense either */
347 case VUT_MINVETERAN: /* Breaks nothing, but has no sense either */
348 case VUT_MINHP: /* Breaks nothing, but has no sense either */
349 case VUT_MINYEAR:
350 case VUT_MINCALFRAG:
351 case VUT_AI_LEVEL:
352 case VUT_TERRAINALTER: /* Local range only */
353 case VUT_STYLE:
354 case VUT_IMPR_GENUS:
355 case VUT_ORIGINAL_OWNER: /* City range -> only one original owner */
356 case VUT_FORM_AGE:
357 /* There can be only one requirement of these types (with current
358 * range limitations)
359 * Requirements might be identical, but we consider multiple
360 * declarations error anyway. */
361
362 ruleset_error(logger, LOG_ERROR,
363 _("%s: Requirement list has multiple %s requirements"),
364 list_for, universal_type_rule_name(&preq->source));
365 return FALSE;
366 break;
367
368 case VUT_TERRAIN:
369 /* There can be only up to max_tiles requirements of these types */
370 if (max_tiles != -1 && rc > max_tiles) {
371 ruleset_error(logger, LOG_ERROR,
372 _("%s: Requirement list has more %s requirements than "
373 "can ever be fulfilled."), list_for,
374 universal_type_rule_name(&preq->source));
375 return FALSE;
376 }
377 break;
378
379 case VUT_TERRAINCLASS:
380 if (rc > 2 || (max_tiles != -1 && rc > max_tiles)) {
381 ruleset_error(logger, LOG_ERROR,
382 _("%s: Requirement list has more %s requirements than "
383 "can ever be fulfilled."), list_for,
384 universal_type_rule_name(&preq->source));
385 return FALSE;
386 }
387 break;
388
389 case VUT_AGE:
390 /* There can be age of the city, unit, and player */
391 if (rc > 3) {
392 ruleset_error(logger, LOG_ERROR,
393 _("%s: Requirement list has more %s requirements than "
394 "can ever be fulfilled."), list_for,
395 universal_type_rule_name(&preq->source));
396 return FALSE;
397 }
398 break;
399
400 case VUT_MINTECHS:
401 /* At ranges 'Player' and 'World' */
402 if (rc > 2) {
403 ruleset_error(logger, LOG_ERROR,
404 _("%s: Requirement list has more %s requirements than "
405 "can ever be fulfilled."), list_for,
406 universal_type_rule_name(&preq->source));
407 return FALSE;
408 }
409 break;
410
411 case VUT_COUNTER:
412 /* Can have multiple, since many counters (also of the same range)
413 * can meet checkpoint */
414 case VUT_SERVERSETTING:
415 /* Can have multiple, since there are many settings. */
416 case VUT_TOPO:
417 /* Can have multiple, since it's flag based (iso & hex) */
418 case VUT_WRAP:
419 /* Can have multiple, since it's flag based (wrapx & wrapy) */
420 case VUT_EXTRA:
421 /* Note that there can be more than 1 extra / tile. */
422 case VUT_MAXTILEUNITS:
423 /* Can require different numbers on e.g. local/adjacent tiles. */
424 case VUT_NATION:
425 /* Can require multiple nations at Team/Alliance/World range. */
426 case VUT_NATIONGROUP:
427 /* Nations can be in multiple groups. */
428 case VUT_NONE:
429 case VUT_ADVANCE:
430 case VUT_TECHFLAG:
431 case VUT_IMPROVEMENT:
432 case VUT_UNITSTATE:
433 case VUT_CITYTILE:
434 case VUT_GOOD:
435 case VUT_UTYPE:
436 case VUT_UCLASS:
437 /* Can check different properties. */
438 case VUT_UTFLAG:
439 case VUT_UCFLAG:
440 case VUT_TERRFLAG:
441 case VUT_ROADFLAG:
442 case VUT_EXTRAFLAG:
443 case VUT_IMPR_FLAG:
444 case VUT_PLAYER_FLAG:
445 case VUT_PLAYER_STATE:
446 case VUT_NATIONALITY:
447 case VUT_MINCULTURE:
448 case VUT_ACHIEVEMENT:
449 case VUT_DIPLREL:
450 case VUT_DIPLREL_TILE:
451 case VUT_DIPLREL_TILE_O:
452 case VUT_DIPLREL_UNITANY:
453 case VUT_DIPLREL_UNITANY_O:
454 /* Can have multiple requirements of these types */
455 case VUT_MINLATITUDE:
456 case VUT_MAXLATITUDE:
457 /* Can have multiple requirements at different ranges.
458 * TODO: Compare to number of legal ranges? */
459 break;
460 case VUT_CITYSTATUS:
461 /* Could check "CITYS_LAST * number of ranges" ? */
462 break;
463 case VUT_COUNT:
464 /* Should never be in requirement vector */
465 fc_assert(FALSE);
466 return FALSE;
467 break;
468 /* No default handling here, as we want compiler warning
469 * if new requirement type is added to enum and it's not handled
470 * here. */
471 }
472 }
473
474 return TRUE;
475}
476
477/**********************************************************************/
493 static bool sanity_check_req_vec(rs_conversion_logger logger,
494 const struct requirement_vector *preqs,
495 bool conjunctive, int max_tiles,
496 const char *list_for)
497{
498 struct req_vec_problem *problem;
499 int reqs_of_type[VUT_COUNT];
500 int local_reqs_of_type[VUT_COUNT];
501 int tile_reqs_of_type[VUT_COUNT];
502
503 /* Initialize requirement counters */
504 memset(reqs_of_type, 0, sizeof(reqs_of_type));
505 memset(tile_reqs_of_type, 0, sizeof(tile_reqs_of_type));
506
507 requirement_vector_iterate(preqs, preq) {
508 if (!sanity_check_req_set(logger, reqs_of_type, local_reqs_of_type,
509 tile_reqs_of_type, preq,
510 conjunctive, max_tiles, list_for)) {
511 return FALSE;
512 }
513 } requirement_vector_iterate_end;
514
515 problem = req_vec_suggest_repair(preqs, req_vec_vector_number, preqs);
516 if (problem != NULL) {
517 ruleset_error(logger, LOG_ERROR, "%s: %s.", list_for, problem->description);
518 req_vec_problem_free(problem);
519 return FALSE;
520 }
521
522 return TRUE;
523}
524
525 typedef struct {
526 struct {
527 bool effect_present[EFT_COUNT];
528 } base_effects;
529 rs_conversion_logger logger;
530} els_data;
531
532/**********************************************************************/
535 static bool effect_list_sanity_cb(struct effect *peffect, void *data)
536{
537 int one_tile = -1; /* TODO: Determine correct value from effect.
538 * -1 disables checking */
539 els_data *els = (els_data *)data;
540 struct astring astr;
541 int i;
542
543 for (i = 0; req_base_effects[i] != EFT_COUNT; i++) {
544 if (peffect->type == req_base_effects[i]) {
545 els->base_effects.effect_present[peffect->type] = TRUE;
546 break;
547 }
548 }
549 for (i = 0; req_base_effects_3_3[i] != EFT_COUNT; i++) {
550 if (peffect->type == req_base_effects_3_3[i]) {
551 els->base_effects.effect_present[peffect->type] = TRUE;
552 break;
553 }
554 }
555
556 if (peffect->type == EFT_ACTION_SUCCESS_TARGET_MOVE_COST) {
557 /* Only unit targets can pay in move fragments. */
558 requirement_vector_iterate(&peffect->reqs, preq) {
559 if (preq->source.kind == VUT_ACTION) {
560 if (action_get_target_kind(preq->source.value.action) != ATK_UNIT) {
561 /* TODO: support for ATK_UNITS could be added. That would require
562 * manually calling action_success_target_pay_mp() in each
563 * supported unit stack targeted action performer (like
564 * action_consequence_success() does) or to have the unit stack
565 * targeted actions return a list of targets. */
566 ruleset_error(els->logger, LOG_ERROR,
567 _("The effect Action_Success_Target_Move_Cost has the"
568 " requirement {%s} but the action %s isn't"
569 " (single) unit targeted."),
570 req_to_fstring(preq, &astr),
571 universal_rule_name(&preq->source));
572 astr_free(&astr);
573 return FALSE;
574 }
575 }
576 } requirement_vector_iterate_end;
577 } else if (peffect->type == EFT_ACTION_SUCCESS_MOVE_COST) {
578 /* Only unit actors can pay in move fragments. */
579 requirement_vector_iterate(&peffect->reqs, preq) {
580 if (preq->source.kind == VUT_ACTION && preq->present) {
581 if (action_get_actor_kind(preq->source.value.action) != AAK_UNIT) {
582 ruleset_error(els->logger, LOG_ERROR,
583 _("The effect Action_Success_Actor_Move_Cost has the"
584 " requirement {%s} but the action %s isn't"
585 " performed by a unit."),
586 req_to_fstring(preq, &astr),
587 universal_rule_name(&preq->source));
588 astr_free(&astr);
589 return FALSE;
590 }
591 }
592 } requirement_vector_iterate_end;
593 } else if (peffect->type == EFT_ACTION_ODDS_PCT
594 || peffect->type == EFT_ACTION_RESIST_PCT) {
595 /* Catch trying to set Action_Odds_Pct for non supported actions. */
596 requirement_vector_iterate(&peffect->reqs, preq) {
597 if (preq->source.kind == VUT_ACTION && preq->present) {
598 if (action_dice_roll_initial_odds(preq->source.value.action)
599 == ACTION_ODDS_PCT_DICE_ROLL_NA) {
600 ruleset_error(els->logger, LOG_ERROR,
601 _("The effect %s has the"
602 " requirement {%s} but the action %s doesn't"
603 " roll the dice to see if it fails."),
604 effect_type_name(peffect->type),
605 req_to_fstring(preq, &astr),
606 universal_rule_name(&preq->source));
607 astr_free(&astr);
608 return FALSE;
609 }
610 }
611 } requirement_vector_iterate_end;
612 }
613
614 if (!sanity_check_req_vec(els->logger, &peffect->reqs, TRUE, one_tile,
615 effect_type_name(peffect->type))) {
616 ruleset_error(els->logger, LOG_ERROR,
617 _("Effects have conflicting or invalid requirements!"));
618
619 return FALSE;
620 }
621
622 return TRUE;
623}
624
625/**********************************************************************/
628 static bool rs_barbarian_units(rs_conversion_logger logger)
629{
630 if (num_role_units(L_BARBARIAN) > 0) {
631 if (num_role_units(L_BARBARIAN_LEADER) == 0) {
632 ruleset_error(logger, LOG_ERROR, _("No role barbarian leader units"));
633 return FALSE;
634 }
635 if (num_role_units(L_BARBARIAN_BUILD) == 0) {
636 ruleset_error(logger, LOG_ERROR, _("No role barbarian build units"));
637 return FALSE;
638 }
639 if (num_role_units(L_BARBARIAN_BOAT) == 0) {
640 ruleset_error(logger, LOG_ERROR, _("No role barbarian ship units"));
641 return FALSE;
642 } else if (num_role_units(L_BARBARIAN_BOAT) > 0) {
643 bool sea_capable = FALSE;
644 struct unit_type *u = get_role_unit(L_BARBARIAN_BOAT, 0);
645
646 terrain_re_active_iterate(pterr) {
647 if (is_ocean(pterr)
648 && BV_ISSET(pterr->native_to, uclass_index(utype_class(u)))) {
649 sea_capable = TRUE;
650 break;
651 }
652 } terrain_re_active_iterate_end;
653
654 if (!sea_capable) {
655 ruleset_error(logger, LOG_ERROR,
656 _("Barbarian boat (%s) needs to be able to move at sea."),
657 utype_rule_name(u));
658 return FALSE;
659 }
660 }
661 if (num_role_units(L_BARBARIAN_SEA) == 0) {
662 ruleset_error(logger, LOG_ERROR, _("No role sea raider barbarian units"));
663 return FALSE;
664 }
665
666 unit_type_re_active_iterate(ptype) {
667 if (utype_has_role(ptype, L_BARBARIAN_BOAT)) {
668 if (ptype->transport_capacity <= 1) {
669 ruleset_error(logger, LOG_ERROR,
670 _("Barbarian boat %s has no capacity for both "
671 "leader and at least one man."),
672 utype_rule_name(ptype));
673 return FALSE;
674 }
675
676 unit_type_re_active_iterate(pbarb) {
677 if (utype_has_role(pbarb, L_BARBARIAN_SEA)
678 || utype_has_role(pbarb, L_BARBARIAN_SEA_TECH)
679 || utype_has_role(pbarb, L_BARBARIAN_LEADER)) {
680 if (!can_unit_type_transport(ptype, utype_class(pbarb))) {
681 ruleset_error(logger, LOG_ERROR,
682 _("Barbarian boat %s cannot transport "
683 "barbarian cargo %s."),
684 utype_rule_name(ptype),
685 utype_rule_name(pbarb));
686 return FALSE;
687 }
688 }
689 } unit_type_re_active_iterate_end;
690 }
691 } unit_type_re_active_iterate_end;
692 }
693
694 return TRUE;
695}
696
697/**********************************************************************/
700 static bool rs_common_units(rs_conversion_logger logger)
701{
702 /* Check some required flags and roles etc: */
703 if (num_role_units(UTYF_WORKERS) == 0) {
704 ruleset_error(logger, LOG_ERROR, _("No flag Worker units"));
705 return FALSE;
706 }
707 if (num_role_units(L_START_EXPLORER) == 0) {
708 ruleset_error(logger, LOG_ERROR, _("No role Start Explorer units"));
709 return FALSE;
710 }
711 if (num_role_units(L_FERRYBOAT) == 0) {
712 ruleset_error(logger, LOG_ERROR, _("No role Ferryboat units"));
713 return FALSE;
714 }
715 if (num_role_units(L_FIRSTBUILD) == 0) {
716 ruleset_error(logger, LOG_ERROR, _("No role Firstbuild units"));
717 return FALSE;
718 }
719
720 if (num_role_units(L_FERRYBOAT) > 0) {
721 bool sea_capable = FALSE;
722 struct unit_type *u = get_role_unit(L_FERRYBOAT, 0);
723
724 terrain_re_active_iterate(pterr) {
725 if (is_ocean(pterr)
726 && BV_ISSET(pterr->native_to, uclass_index(utype_class(u)))) {
727 sea_capable = TRUE;
728 break;
729 }
730 } terrain_re_active_iterate_end;
731
732 if (!sea_capable) {
733 ruleset_error(logger, LOG_ERROR,
734 _("Ferryboat (%s) needs to be able to move at sea."),
735 utype_rule_name(u));
736 return FALSE;
737 }
738 }
739
740 if (num_role_units(L_PARTISAN) == 0
741 && effect_cumulative_max(EFT_INSPIRE_PARTISANS, NULL, 0) > 0) {
742 ruleset_error(logger, LOG_ERROR,
743 _("Inspire_Partisans effect present, "
744 "but no units with partisan role."));
745 return FALSE;
746 }
747
748 return TRUE;
749}
750
751/**********************************************************************/
754 static bool rs_buildings(rs_conversion_logger logger)
755{
756 /* Special Genus */
757 improvement_re_active_iterate(pimprove) {
758 if (improvement_has_flag(pimprove, IF_GOLD)
759 && pimprove->genus != IG_CONVERT) {
760 ruleset_error(logger, LOG_ERROR,
761 _("Gold producing improvement %s with genus other than \"Convert\""),
762 improvement_rule_name(pimprove));
763
764 return FALSE;
765 }
766 if (improvement_has_flag(pimprove, IF_DISASTER_PROOF)
767 && pimprove->genus != IG_IMPROVEMENT) {
768 ruleset_error(logger, LOG_ERROR,
769 _("Disasterproof improvement %s with genus other than \"Improvement\""),
770 improvement_rule_name(pimprove));
771
772 return FALSE;
773 }
774 if (pimprove->genus != IG_SPECIAL
775 && (get_potential_improvement_bonus(pimprove, NULL, EFT_SS_STRUCTURAL,
776 RPT_POSSIBLE, FALSE)
777 || get_potential_improvement_bonus(pimprove, NULL, EFT_SS_COMPONENT,
778 RPT_POSSIBLE, FALSE)
779 || get_potential_improvement_bonus(pimprove, NULL, EFT_SS_MODULE,
780 RPT_POSSIBLE, FALSE))) {
781 ruleset_error(logger, LOG_ERROR,
782 _("Space part %s with genus other than \"Special\""),
783 improvement_rule_name(pimprove));
784 return FALSE;
785 }
786
787 if (!is_building_sellable(pimprove) && pimprove->upkeep != 0) {
788 ruleset_error(logger, LOG_ERROR,
789 _("%s is a nonsellable building with a nonzero upkeep value"),
790 improvement_rule_name(pimprove));
791 return FALSE;
792 }
793 } improvement_re_active_iterate_end;
794
795 return TRUE;
796}
797
798/**********************************************************************/
801 static bool sanity_check_boolean_effects(rs_conversion_logger logger)
802{
803 enum effect_type boolean_effects[] =
804 {
805 EFT_ANY_GOVERNMENT,
806 EFT_ENABLE_NUKE,
807 EFT_ENABLE_SPACE,
808 EFT_HAVE_EMBASSIES,
809 EFT_NO_ANARCHY,
810 EFT_NUKE_PROOF,
811 EFT_REVEAL_CITIES,
812 EFT_REVEAL_MAP,
813 EFT_SIZE_UNLIMIT,
814 EFT_SS_STRUCTURAL,
815 EFT_SS_COMPONENT,
816 EFT_NO_UNHAPPY,
817 EFT_RAPTURE_GROW,
818 EFT_HAS_SENATE,
819 EFT_INSPIRE_PARTISANS,
820 EFT_HAPPINESS_TO_GOLD,
821 EFT_FANATICS,
822 EFT_NO_DIPLOMACY,
823 EFT_GOV_CENTER,
824 EFT_NOT_TECH_SOURCE,
825 EFT_VICTORY,
826 EFT_HAVE_CONTACTS,
827 EFT_COUNT
828 };
829 int i;
830 bool ret = TRUE;
831
832 for (i = 0; boolean_effects[i] != EFT_COUNT; i++) {
833 if (effect_cumulative_min(boolean_effects[i], NULL) < 0
834 && effect_cumulative_max(boolean_effects[i], NULL, 0) == 0) {
835 ruleset_error(logger, LOG_ERROR,
836 _("Boolean effect %s can get disabled, but it can't get "
837 "enabled before that."),
838 effect_type_name(boolean_effects[i]));
839 ret = FALSE;
840 }
841 }
842
843 return ret;
844}
845
846/**********************************************************************/
853 bool sanity_check_ruleset_data(struct rscompat_info *compat)
854{
855 int num_utypes;
856 int i;
857 bool ok = TRUE; /* Store failures to variable instead of returning
858 * immediately so all errors get printed, not just first
859 * one. */
860 bool default_gov_failed = FALSE;
861 bool obsoleted_by_loop = FALSE;
862 els_data els;
863 rs_conversion_logger logger = ((compat != NULL) ? compat->log_cb : NULL);
864
865 if (!sanity_check_metadata(logger)) {
866 ok = FALSE;
867 }
868
869 if (game.info.tech_cost_style == TECH_COST_CIV1CIV2
870 && game.info.free_tech_method == FTM_CHEAPEST) {
871 ruleset_error(logger, LOG_ERROR,
872 _("Cost based free tech method, but tech cost style "
873 "\"Civ I|II\" so all techs cost the same."));
874 ok = FALSE;
875 }
876
877 /* Advances. */
878 advance_re_active_iterate(padvance) {
879 for (i = AR_ONE; i < AR_SIZE; i++) {
880 const struct advance *preq;
881
882 if (i == AR_ROOT) {
883 /* Self rootreq is a feature. */
884 continue;
885 }
886
887 preq = advance_requires(padvance, i);
888
889 if (A_NEVER == preq) {
890 continue;
891 } else if (preq == padvance) {
892 ruleset_error(logger, LOG_ERROR, _("Tech \"%s\" requires itself."),
893 advance_rule_name(padvance));
894 ok = FALSE;
895 continue;
896 }
897
898 advance_req_iterate(preq, preqreq) {
899 if (preqreq == padvance) {
900 ruleset_error(logger, LOG_ERROR,
901 _("Tech \"%s\" requires itself indirectly via \"%s\"."),
902 advance_rule_name(padvance),
903 advance_rule_name(preq));
904 ok = FALSE;
905 }
906 } advance_req_iterate_end;
907 }
908
909 requirement_vector_iterate(&(padvance->research_reqs), preq) {
910 if (preq->source.kind == VUT_ADVANCE) {
911 /* Don't allow this even if allowing changing reqs. Players will
912 * expect all tech reqs to appear in the client tech tree. That
913 * should be taken care of first. */
914 ruleset_error(logger, LOG_ERROR,
915 _("Tech \"%s\" requires a tech in its research_reqs."
916 " This isn't supported yet. Please keep using req1"
917 " and req2 like before."),
918 advance_rule_name(padvance));
919 ok = FALSE;
920 } else if (is_req_unchanging(NULL, preq) < REQUCH_HACK
921 /* If we get an obsolete improvement before the game,
922 * almost surely it is going to become not obsolete later.
923 * This check must catch it. */) {
924 struct astring astr;
925
926 /* Only support unchanging requirements until the reachability code
927 * can handle it and the tech tree can display changing
928 * requirements. */
929 ruleset_error(logger, LOG_ERROR,
930 _("Tech \"%s\" has the requirement %s in its"
931 " research_reqs. This requirement may change during"
932 " the game. Changing requirements aren't supported"
933 " yet."),
934 advance_rule_name(padvance),
935 req_to_fstring(preq, &astr));
936 astr_free(&astr);
937 ok = FALSE;
938 }
939 } requirement_vector_iterate_end;
940
941 if (padvance->bonus_message != NULL) {
942 if (!formats_match(padvance->bonus_message, "%s")) {
943 ruleset_error(logger, LOG_ERROR,
944 _("Tech \"%s\" bonus message is not format with %%s "
945 "for a bonus tech name."),
946 advance_rule_name(padvance));
947 ok = FALSE;
948 }
949 }
950 } advance_re_active_iterate_end;
951
952 if (game.default_government == game.government_during_revolution) {
953 ruleset_error(logger, LOG_ERROR,
954 _("The government form %s reserved for revolution handling "
955 "has been set as default_government."),
956 government_rule_name(game.government_during_revolution));
957 ok = FALSE;
958 default_gov_failed = TRUE;
959 }
960
961 /* Check that all players can have their initial techs */
962 nations_re_active_iterate(pnation) {
963 int techi;
964
965 /* Check global initial techs */
966 for (techi = 0; techi < MAX_NUM_TECH_LIST
967 && game.rgame.global_init_techs[techi] != A_LAST; techi++) {
968 Tech_type_id tech = game.rgame.global_init_techs[techi];
969 struct advance *a = valid_advance_by_number(tech);
970
971 if (a == NULL) {
972 ruleset_error(logger, LOG_ERROR,
973 _("Tech %s does not exist, but is initial "
974 "tech for everyone."),
975 advance_rule_name(advance_by_number(tech)));
976 ok = FALSE;
977 } else if (advance_by_number(A_NONE) != a->require[AR_ROOT]
978 && !nation_has_initial_tech(pnation, a->require[AR_ROOT])) {
979 /* Nation has no root_req for tech */
980 ruleset_error(logger, LOG_ERROR,
981 _("Tech %s is initial for everyone, but %s has "
982 "no root_req for it."),
983 advance_rule_name(a),
984 nation_rule_name(pnation));
985 ok = FALSE;
986 }
987 }
988
989 /* Check national initial techs */
990 for (techi = 0;
991 techi < MAX_NUM_TECH_LIST && pnation->init_techs[techi] != A_LAST;
992 techi++) {
993 Tech_type_id tech = pnation->init_techs[techi];
994 struct advance *a = valid_advance_by_number(tech);
995
996 if (a == NULL) {
997 ruleset_error(logger, LOG_ERROR,
998 _("Tech %s does not exist, but is tech for %s."),
999 advance_rule_name(advance_by_number(tech)),
1000 nation_rule_name(pnation));
1001 ok = FALSE;
1002 } else if (advance_by_number(A_NONE) != a->require[AR_ROOT]
1003 && !nation_has_initial_tech(pnation, a->require[AR_ROOT])) {
1004 /* Nation has no root_req for tech */
1005 ruleset_error(logger, LOG_ERROR,
1006 _("Tech %s is initial for %s, but they have "
1007 "no root_req for it."),
1008 advance_rule_name(a),
1009 nation_rule_name(pnation));
1010 ok = FALSE;
1011 }
1012 }
1013
1014 /* Check national initial buildings */
1015 if (nation_barbarian_type(pnation) != NOT_A_BARBARIAN
1016 && pnation->init_buildings[0] != B_LAST) {
1017 ruleset_error(logger, LOG_ERROR,
1018 _("Barbarian nation %s has init_buildings set but will "
1019 "never see them"), nation_rule_name(pnation));
1020 }
1021
1022 if (!default_gov_failed && pnation->init_government == game.government_during_revolution) {
1023 ruleset_error(logger, LOG_ERROR,
1024 _("The government form %s reserved for revolution "
1025 "handling has been set as initial government for %s."),
1026 government_rule_name(game.government_during_revolution),
1027 nation_rule_name(pnation));
1028 ok = FALSE;
1029 }
1030 } nations_re_active_iterate_end;
1031
1032 /* Check against unit upgrade loops */
1033 num_utypes = game.control.num_unit_types;
1034 unit_type_re_active_iterate(putype) {
1035 int chain_length = 0;
1036 const struct unit_type *upgraded = putype;
1037
1038 while (upgraded != NULL && !obsoleted_by_loop) {
1039 upgraded = upgraded->obsoleted_by;
1040 chain_length++;
1041 if (chain_length > num_utypes) {
1042 ruleset_error(logger, LOG_ERROR,
1043 _("There seems to be obsoleted_by loop in update "
1044 "chain that starts from %s"),
1045 utype_rule_name(putype));
1046 ok = FALSE;
1047 obsoleted_by_loop = TRUE;
1048 }
1049 }
1050 } unit_type_re_active_iterate_end;
1051
1052 /* Some unit type properties depend on other unit type properties to work
1053 * properly. */
1054 unit_type_re_active_iterate(putype) {
1055 /* "Spy" is a better "Diplomat". Until all the places that assume that
1056 * "Diplomat" is set if "Spy" is set is changed this limitation must be
1057 * kept. */
1058 if (utype_has_flag(putype, UTYF_SPY)
1059 && !utype_has_flag(putype, UTYF_DIPLOMAT)) {
1060 ruleset_error(logger, LOG_ERROR,
1061 _("The unit type '%s' has the 'Spy' unit type flag but "
1062 "not the 'Diplomat' unit type flag."),
1063 utype_rule_name(putype));
1064 ok = FALSE;
1065 }
1066 } unit_type_re_active_iterate_end;
1067
1068 /* Check that unit type fields are in range. */
1069 unit_type_re_active_iterate(putype) {
1070 if (putype->paratroopers_range < 0
1071 || putype->paratroopers_range > UNIT_MAX_PARADROP_RANGE) {
1072 /* Paradrop range is limited by the network protocol. */
1073 ruleset_error(logger, LOG_ERROR,
1074 _("The paratroopers_range of the unit type '%s' is %d. "
1075 "That is out of range. Max range is %d."),
1076 utype_rule_name(putype),
1077 putype->paratroopers_range, UNIT_MAX_PARADROP_RANGE);
1078 ok = FALSE;
1079 }
1080 /* never fires if game.scenario.prevent_new_cities is TRUE */
1081 if ((putype->city_size <= 0 || putype->city_size > MAX_CITY_SIZE)
1082 && utype_is_cityfounder(putype)) {
1083 ruleset_error(logger, LOG_ERROR,
1084 _("Unit type '%s' would build size %d cities. "
1085 "City sizes must be from 1 to %d."),
1086 utype_rule_name(putype), putype->city_size,
1087 MAX_CITY_SIZE);
1088 ok = FALSE;
1089 }
1090 } unit_type_re_active_iterate_end;
1091
1092 memset(&els, 0, sizeof(els));
1093 els.logger = logger;
1094
1095 /* Check requirement sets against conflicting requirements.
1096 * For effects check also other sanity in the same iteration */
1097 if (!iterate_effect_cache(effect_list_sanity_cb, &els)) {
1098 ok = FALSE;
1099 }
1100
1101 for (i = 0; req_base_effects[i] != EFT_COUNT; i++) {
1102 if (!els.base_effects.effect_present[req_base_effects[i]]) {
1103 ruleset_error(logger, LOG_ERROR,
1104 _("There is no base %s effect."),
1105 effect_type_name(req_base_effects[i]));
1106 ok = FALSE;
1107 }
1108 }
1109 for (i = 0; req_base_effects_3_3[i] != EFT_COUNT; i++) {
1110 if (!els.base_effects.effect_present[req_base_effects_3_3[i]]) {
1111 const char *ename = effect_type_name(req_base_effects_3_3[i]);
1112
1113 if (compat != NULL && compat->compat_mode && compat->version < RSFORMAT_3_3) {
1114 log_deprecation("There is no base %s effect.", ename);
1115 if (compat->log_cb != NULL) {
1116 char buf[512];
1117
1118 fc_snprintf(buf, sizeof(buf), _("Missing base %s effect. Please add one."), ename);
1119 compat->log_cb(buf);
1120 }
1121 } else {
1122 ruleset_error(logger, LOG_ERROR,
1123 _("There is no base %s effect."), ename);
1124 ok = FALSE;
1125 }
1126 }
1127 }
1128
1129 if (!sanity_check_boolean_effects(logger)) {
1130 ok = FALSE;
1131 }
1132
1133 /* Others use requirement vectors */
1134
1135 /* Disasters */
1136 disaster_type_re_active_iterate(pdis) {
1137 if (!sanity_check_req_vec(logger, &pdis->reqs, TRUE, -1,
1138 disaster_rule_name(pdis))) {
1139 ruleset_error(logger, LOG_ERROR,
1140 _("Disasters have conflicting or invalid requirements!"));
1141 ok = FALSE;
1142 }
1143 } disaster_type_re_active_iterate_end;
1144
1145 /* Goods */
1146 goods_type_re_active_iterate(pgood) {
1147 if (!sanity_check_req_vec(logger, &pgood->reqs, TRUE, -1,
1148 goods_rule_name(pgood))) {
1149 ruleset_error(logger, LOG_ERROR,
1150 _("Goods have conflicting or invalid requirements!"));
1151 ok = FALSE;
1152 }
1153 } goods_type_re_active_iterate_end;
1154
1155 /* Buildings */
1156 improvement_re_active_iterate(pimprove) {
1157 if (!sanity_check_req_vec(logger, &pimprove->reqs, TRUE, -1,
1158 improvement_rule_name(pimprove))) {
1159 ruleset_error(logger, LOG_ERROR,
1160 _("Buildings have conflicting or invalid requirements!"));
1161 ok = FALSE;
1162 }
1163 if (!sanity_check_req_vec(logger, &pimprove->obsolete_by, FALSE, -1,
1164 improvement_rule_name(pimprove))) {
1165 ruleset_error(logger, LOG_ERROR,
1166 _("Buildings have conflicting or invalid obsolescence req!"));
1167 ok = FALSE;
1168 }
1169 } improvement_re_active_iterate_end;
1170
1171 /* Governments */
1172 governments_re_active_iterate(pgov) {
1173 if (!sanity_check_req_vec(logger, &pgov->reqs, TRUE, -1,
1174 government_rule_name(pgov))) {
1175 ruleset_error(logger, LOG_ERROR,
1176 _("Governments have conflicting or invalid requirements!"));
1177 ok = FALSE;
1178 }
1179 } governments_re_active_iterate_end;
1180
1181 /* Specialists */
1182 specialist_type_re_active_iterate(psp) {
1183 if (!sanity_check_req_vec(logger, &psp->reqs, TRUE, -1,
1184 specialist_rule_name(psp))) {
1185 ruleset_error(logger, LOG_ERROR,
1186 _("Specialists have conflicting or invalid requirements!"));
1187 ok = FALSE;
1188 }
1189 } specialist_type_re_active_iterate_end;
1190
1191 /* Extras */
1192 extra_type_re_active_iterate(pextra) {
1193 if (!sanity_check_req_vec(logger, &pextra->reqs, TRUE, -1,
1194 extra_rule_name(pextra))) {
1195 ruleset_error(logger, LOG_ERROR,
1196 _("Extras have conflicting or invalid requirements!"));
1197 ok = FALSE;
1198 }
1199 if (!sanity_check_req_vec(logger, &pextra->rmreqs, TRUE, -1,
1200 extra_rule_name(pextra))) {
1201 ruleset_error(logger, LOG_ERROR,
1202 _("Extras have conflicting or invalid removal requirements!"));
1203 ok = FALSE;
1204 }
1205 if ((requirement_vector_size(&pextra->rmreqs) > 0)
1206 && !(pextra->rmcauses
1207 & (ERM_ENTER | ERM_CLEAN | ERM_PILLAGE))) {
1208 ruleset_error(logger, LOG_WARN,
1209 _("Requirements for extra removal defined but not "
1210 "a valid remove cause!"));
1211 }
1212 } extra_type_re_active_iterate_end;
1213
1214 /* Roads */
1215 extra_type_by_cause_iterate(EC_ROAD, pextra) {
1216 struct road_type *proad = extra_road_get(pextra);
1217
1218 extra_type_list_iterate(proad->integrators, iextra) {
1219 struct road_type *iroad = extra_road_get(iextra);
1220 int pnbr = road_number(proad);
1221
1222 if (pnbr != road_number(iroad)
1223 && !BV_ISSET(iroad->integrates, pnbr)) {
1224 /* We don't support non-symmetric integrator relationships yet. */
1225 ruleset_error(logger, LOG_ERROR,
1226 _("Road '%s' integrates with '%s' but not vice versa!"),
1227 extra_rule_name(pextra),
1228 extra_rule_name(iextra));
1229 ok = FALSE;
1230 }
1231 } extra_type_list_iterate_end;
1232 } extra_type_by_cause_iterate_end;
1233
1234 /* City styles */
1235 for (i = 0; i < game.control.num_city_styles; i++) {
1236 if (!sanity_check_req_vec(logger, &city_styles[i].reqs, TRUE, -1,
1237 city_style_rule_name(i))) {
1238 ruleset_error(logger, LOG_ERROR,
1239 _("City styles have conflicting or invalid requirements!"));
1240 ok = FALSE;
1241 }
1242 }
1243
1244 /* Actions */
1245 action_iterate(act) {
1246 struct action *paction = action_by_number(act);
1247
1248 if (!actres_legal_target_kind(paction->result, paction->target_kind)) {
1249 ruleset_error(logger, LOG_ERROR,
1250 _("Action \"%s\": unsupported target kind %s."),
1251 action_id_rule_name(act),
1252 action_target_kind_name(paction->target_kind));
1253 ok = FALSE;
1254 }
1255
1256 if (paction->min_distance < 0) {
1257 ruleset_error(logger, LOG_ERROR,
1258 _("Action %s: negative min distance (%d)."),
1259 action_id_rule_name(act), paction->min_distance);
1260 ok = FALSE;
1261 }
1262
1263 if (paction->min_distance > ACTION_DISTANCE_LAST_NON_SIGNAL) {
1264 ruleset_error(logger, LOG_ERROR,
1265 _("Action %s: min distance (%d) larger than "
1266 "any distance on a map can be (%d)."),
1267 action_id_rule_name(act), paction->min_distance,
1268 ACTION_DISTANCE_LAST_NON_SIGNAL);
1269 ok = FALSE;
1270 }
1271
1272 if (paction->max_distance > ACTION_DISTANCE_MAX) {
1273 ruleset_error(logger, LOG_ERROR,
1274 _("Action %s: max distance is %d. "
1275 "A map can't be that big."),
1276 action_id_rule_name(act), paction->max_distance);
1277 ok = FALSE;
1278 }
1279
1280 if (!action_distance_inside_max(paction, paction->min_distance)) {
1281 ruleset_error(logger, LOG_ERROR,
1282 _("Action %s: min distance is %d but max distance is %d."),
1283 action_id_rule_name(act),
1284 paction->min_distance, paction->max_distance);
1285 ok = FALSE;
1286 }
1287
1288 action_iterate(blocker) {
1289 if (BV_ISSET(paction->blocked_by, blocker)
1290 && action_id_get_target_kind(blocker) == ATK_UNIT
1291 && action_id_get_target_kind(act) != ATK_UNIT) {
1292 /* Can't find an individual unit target to evaluate the blocking
1293 * action against. (A tile may have more than one individual
1294 * unit) */
1295 ruleset_error(logger, LOG_ERROR,
1296 _("The action %s can't block %s."),
1297 action_id_rule_name(blocker),
1298 action_id_rule_name(act));
1299 ok = FALSE;
1300 }
1301 } action_iterate_end;
1302
1303 action_enabler_list_re_iterate(action_enablers_for_action(act), enabler) {
1304 if (!sanity_check_req_vec(logger, &(enabler->actor_reqs), TRUE, -1,
1305 "Action Enabler Actor Reqs")
1306 || !sanity_check_req_vec(logger, &(enabler->target_reqs), TRUE, -1,
1307 "Action Enabler Target Reqs")) {
1308 ruleset_error(logger, LOG_ERROR,
1309 _("Action enabler for %s has conflicting or invalid "
1310 "requirements!"), action_id_rule_name(act));
1311 ok = FALSE;
1312 }
1313
1314 if (action_get_target_kind(enabler_get_action(enabler)) == ATK_SELF) {
1315 /* Special test for self targeted actions. */
1316
1317 if (requirement_vector_size(&(enabler->target_reqs)) > 0) {
1318 /* Shouldn't have target requirements since the action doesn't
1319 * have a target. */
1320 ruleset_error(logger, LOG_ERROR,
1321 _("An action enabler for %s has a target "
1322 "requirement vector. %s doesn't have a target."),
1323 action_id_rule_name(act),
1324 action_id_rule_name(act));
1325 ok = FALSE;
1326 }
1327 }
1328
1329 requirement_vector_iterate(&(enabler->target_reqs), preq) {
1330 if (preq->source.kind == VUT_DIPLREL
1331 && preq->range == REQ_RANGE_LOCAL) {
1332 struct astring astr;
1333
1334 /* A Local DiplRel requirement can be expressed as a requirement
1335 * in actor_reqs. Demand that it is there. This avoids breaking
1336 * code that reasons about actions. */
1337 ruleset_error(logger, LOG_ERROR,
1338 _("Action enabler for %s has a local DiplRel "
1339 "requirement %s in target_reqs! Please read the "
1340 "section \"Requirement vector rules\" in "
1341 "doc/README.actions"),
1342 action_id_rule_name(act),
1343 req_to_fstring(preq, &astr));
1344 astr_free(&astr);
1345 ok = FALSE;
1346 }
1347 } requirement_vector_iterate_end;
1348
1349 if (compat == NULL || !compat->compat_mode
1350 || compat->version >= RSFORMAT_3_3) {
1351 /* Support for letting some of the following hard requirements be
1352 * implicit were retired in Freeciv 3.0. Others were retired later.
1353 * Make sure that the opposite of each hard action requirement
1354 * blocks all its action enablers. */
1355
1356 struct req_vec_problem *problem
1357 = action_enabler_suggest_repair(enabler);
1358
1359 if (problem != NULL) {
1360 ruleset_error(logger, LOG_ERROR, "%s", problem->description);
1361 req_vec_problem_free(problem);
1362 ok = FALSE;
1363 }
1364
1365 problem = action_enabler_suggest_improvement(enabler);
1366 if (problem != NULL) {
1367 /* There is a potential for improving this enabler. */
1368 log_deprecation("%s", problem->description);
1369 req_vec_problem_free(problem);
1370 }
1371 }
1372 } action_enabler_list_re_iterate_end;
1373
1374 if (BV_ISSET(game.info.diplchance_initial_odds, paction->id)
1375 /* The action performer, action_dice_roll_initial_odds() and the
1376 * action probability calculation in action_prob() must probably all
1377 * be updated to add a new action here. */
1378 && !(action_has_result_safe(paction, ACTRES_STRIKE_BUILDING)
1379 || action_has_result_safe(paction, ACTRES_STRIKE_PRODUCTION)
1380 || action_has_result_safe(paction, ACTRES_SPY_SPREAD_PLAGUE)
1381 || action_has_result_safe(paction, ACTRES_SPY_POISON)
1382 || action_has_result_safe(paction, ACTRES_SPY_STEAL_TECH)
1383 || action_has_result_safe(paction,
1384 ACTRES_SPY_TARGETED_STEAL_TECH)
1385 || action_has_result_safe(paction, ACTRES_SPY_INCITE_CITY)
1386 || action_has_result_safe(paction, ACTRES_SPY_SABOTAGE_CITY)
1387 || action_has_result_safe(paction,
1388 ACTRES_SPY_TARGETED_SABOTAGE_CITY)
1389 || action_has_result_safe(paction,
1390 ACTRES_SPY_SABOTAGE_CITY_PRODUCTION)
1391 || action_has_result_safe(paction, ACTRES_SPY_STEAL_GOLD)
1392 || action_has_result_safe(paction, ACTRES_STEAL_MAPS)
1393 || action_has_result_safe(paction, ACTRES_SPY_NUKE))) {
1394 ruleset_error(logger, LOG_ERROR,
1395 _("diplchance_initial_odds: \"%s\" not supported."),
1396 action_rule_name(paction));
1397 ok = FALSE;
1398 }
1399
1400 if (BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER)
1401 && BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN)) {
1402 ruleset_error(logger, LOG_ERROR,
1403 _("%s both enters and frightens a hut at the same time."),
1404 action_rule_name(paction));
1405 ok = FALSE;
1406 }
1407 } action_iterate_end;
1408
1409 /* Auto attack */
1410 {
1411 struct action_auto_perf *auto_perf;
1412
1413 auto_perf = action_auto_perf_slot_number(ACTION_AUTO_MOVED_ADJ);
1414
1415 action_auto_perf_actions_iterate(auto_perf, act_id) {
1416 struct action *paction = action_by_number(act_id);
1417
1418 if (!action_has_result(paction, ACTRES_CAPTURE_UNITS)
1419 && !action_has_result(paction, ACTRES_BOMBARD)
1420 && !action_has_result(paction, ACTRES_ATTACK)
1421 && !action_has_result(paction, ACTRES_COLLECT_RANSOM)) {
1422 /* Only allow removing and changing the order of old auto
1423 * attack actions for now. Other actions need more testing and
1424 * fixing of issues caused by a worst case action probability of
1425 * 0%. */
1426 ruleset_error(logger, LOG_ERROR,
1427 _("auto_attack: %s not supported in"
1428 " attack_actions."),
1429 action_rule_name(paction));
1430 ok = FALSE;
1431 }
1432 } action_auto_perf_actions_iterate_end;
1433 }
1434
1435 /* There must be basic city style for each nation style to start with */
1436 styles_re_active_iterate(pstyle) {
1437 if (basic_city_style_for_style(pstyle) < 0) {
1438 ruleset_error(logger, LOG_ERROR,
1439 _("There's no basic city style for nation style %s"),
1440 style_rule_name(pstyle));
1441 ok = FALSE;
1442 }
1443 } styles_re_active_iterate_end;
1444
1445 /* Music styles */
1446 music_styles_re_active_iterate(pmus) {
1447 if (!sanity_check_req_vec(logger, &pmus->reqs, TRUE, -1, "Music Style")) {
1448 ruleset_error(logger, LOG_ERROR,
1449 _("Music Styles have conflicting or invalid requirements!"));
1450 ok = FALSE;
1451 }
1452 } music_styles_re_active_iterate_end;
1453
1454 terrain_re_active_iterate(pterr) {
1455 if (pterr->animal != NULL) {
1456 if (!is_native_to_class(utype_class(pterr->animal), pterr, NULL)) {
1457 ruleset_error(logger, LOG_ERROR,
1458 _("%s has %s as animal to appear, but it's not native to the terrain."),
1459 terrain_rule_name(pterr), utype_rule_name(pterr->animal));
1460 ok = FALSE;
1461 }
1462 }
1463
1464 terrain_resources_iterate(pterr, pres, freq) {
1465 (void) freq;
1466 if (!is_extra_caused_by(pres, EC_RESOURCE)) {
1467 ruleset_error(logger, LOG_ERROR,
1468 _("%s has %s as a resource, but it's not a resource extra."),
1469 terrain_rule_name(pterr), extra_rule_name(pres));
1470 ok = FALSE;
1471 }
1472 } terrain_resources_iterate_end;
1473 } terrain_re_active_iterate_end;
1474
1475 /* Check that all unit classes can exist somewhere */
1476 unit_class_re_active_iterate(pclass) {
1477 if (!uclass_has_flag(pclass, UCF_BUILD_ANYWHERE)) {
1478 bool can_exist = FALSE;
1479
1480 terrain_re_active_iterate(pterr) {
1481 if (BV_ISSET(pterr->native_to, uclass_index(pclass))) {
1482 can_exist = TRUE;
1483 break;
1484 }
1485 } terrain_re_active_iterate_end;
1486
1487 if (!can_exist) {
1488 extra_type_re_active_iterate(pextra) {
1489 if (BV_ISSET(pextra->native_to, uclass_index(pclass))
1490 && extra_has_flag(pextra, EF_NATIVE_TILE)) {
1491 can_exist = TRUE;
1492 break;
1493 }
1494 } extra_type_re_active_iterate_end;
1495 }
1496
1497 if (!can_exist) {
1498 ruleset_error(logger, LOG_ERROR,
1499 _("Unit class %s cannot exist anywhere."),
1500 uclass_rule_name(pclass));
1501 ok = FALSE;
1502 }
1503 }
1504 } unit_class_re_active_iterate_end;
1505
1506 achievements_re_active_iterate(pach) {
1507 if (!pach->unique && pach->cons_msg == NULL) {
1508 ruleset_error(logger, LOG_ERROR,
1509 _("Achievement %s has no message for consecutive gainers though "
1510 "it's possible to be gained by multiple players"),
1511 achievement_rule_name(pach));
1512 ok = FALSE;
1513 }
1514 } achievements_re_active_iterate_end;
1515
1516 if (game.server.ruledit.embedded_nations != NULL) {
1517 int nati;
1518
1519 for (nati = 0; nati < game.server.ruledit.embedded_nations_count; nati++) {
1520 struct nation_type *pnat
1521 = nation_by_rule_name(game.server.ruledit.embedded_nations[nati]);
1522
1523 if (pnat == NULL) {
1524 ruleset_error(logger, LOG_ERROR,
1525 _("There's nation %s listed in embedded nations, but there's "
1526 "no such nation."),
1527 game.server.ruledit.embedded_nations[nati]);
1528 ok = FALSE;
1529 }
1530 }
1531 }
1532
1533 if (ok) {
1534 ok = rs_common_units(logger);
1535 }
1536 if (ok) {
1537 ok = rs_barbarian_units(logger);
1538 }
1539 if (ok) {
1540 ok = rs_buildings(logger);
1541 }
1542
1543 return ok;
1544}
1545
1546/**********************************************************************/
1551 bool autoadjust_ruleset_data(void)
1552{
1553 bool ok = TRUE;
1554
1555 extra_type_by_cause_iterate(EC_RESOURCE, pextra) {
1556 extra_type_by_cause_iterate(EC_RESOURCE, pextra2) {
1557 if (pextra != pextra2) {
1558 int idx = extra_index(pextra2);
1559
1560 if (!BV_ISSET(pextra->conflicts, idx)) {
1561 log_debug("Autoconflicting resource %s with %s",
1562 extra_rule_name(pextra), extra_rule_name(pextra2));
1563 BV_SET(pextra->conflicts, extra_index(pextra2));
1564 }
1565 }
1566 } extra_type_by_cause_iterate_end;
1567 } extra_type_by_cause_iterate_end;
1568
1569 /* Hard coded action blocking. */
1570 {
1571 const struct {
1572 const enum action_result blocked;
1573 const enum action_result blocker;
1574 } must_block[] = {
1575 /* Hard code that Help Wonder blocks Disband Unit Recover. This must be done
1576 * because caravan_shields makes it possible to avoid the
1577 * consequences of choosing to do Disband Unit Recover rather than having it
1578 * do Help Wonder.
1579 *
1580 * Explanation: Disband Unit Recover adds 50% of the shields used to produce
1581 * the unit to the production of the city where it is located. Help
1582 * Wonder adds 100%. If a unit that can do Help Wonder is disbanded with
1583 * production recovery in a city and the production later is changed
1584 * to something that can receive help from Help Wonder the remaining 50%
1585 * of the shields are added. This can be done because the city remembers
1586 * them in caravan_shields.
1587 *
1588 * If a unit that can do Help Wonder intentionally is disbanded with recovery
1589 * rather than making it do Help Wonder its shields will still be
1590 * remembered. The target city that got 50% of the shields can
1591 * therefore get 100% of them by changing its production. This trick
1592 * makes the ability to select Disband Unit Recover when Help Wonder is legal
1593 * pointless. */
1594 { ACTRES_DISBAND_UNIT_RECOVER, ACTRES_HELP_WONDER },
1595
1596 /* Allowing regular disband when ACTION_HELP_WONDER or
1597 * ACTION_DISBAND_UNIT_RECOVER is legal while ACTION_HELP_WONDER always
1598 * blocks ACTION_DISBAND_UNIT_RECOVER doesn't work well with the force_*
1599 * semantics. Should move to the ruleset once it has blocked_by
1600 * semantics. */
1601 { ACTRES_DISBAND_UNIT, ACTRES_HELP_WONDER },
1602 { ACTRES_DISBAND_UNIT, ACTRES_DISBAND_UNIT_RECOVER },
1603
1604 /* Hard code that the ability to perform a regular attack blocks city
1605 * conquest. Is redundant as long as the requirement that the target
1606 * tile has no units remains hard coded. Kept "just in case" that
1607 * changes. */
1608 { ACTRES_CONQUER_CITY, ACTRES_ATTACK },
1609
1610 /* Hard code that the ability to perform a regular attack blocks
1611 * extras conquest. Is redundant as long as the requirement that the
1612 * target tile has no non-allied units remains hard coded. Kept "just
1613 * in case" that changes. */
1614 { ACTRES_CONQUER_EXTRAS, ACTRES_ATTACK },
1615
1616 /* Hard code that the ability to enter or frighten a hut blocks
1617 * regular disembarking. */
1618 { ACTRES_TRANSPORT_DISEMBARK, ACTRES_CONQUER_EXTRAS },
1619 { ACTRES_TRANSPORT_DISEMBARK, ACTRES_HUT_ENTER },
1620 { ACTRES_TRANSPORT_DISEMBARK, ACTRES_HUT_FRIGHTEN },
1621 };
1622
1623 int i;
1624
1625 for (i = 0; i < ARRAY_SIZE(must_block); i++) {
1626 enum action_result blocked_result = must_block[i].blocked;
1627 enum action_result blocker_result = must_block[i].blocker;
1628
1629 action_by_result_iterate(blocked, blocked_result) {
1630 action_by_result_iterate(blocker, blocker_result) {
1631 if (!action_would_be_blocked_by(blocked, blocker)) {
1632 log_verbose("Autoblocking %s with %s",
1633 action_rule_name(blocked),
1634 action_rule_name(blocker));
1635 BV_SET(blocked->blocked_by, action_id(blocker));
1636 }
1637 } action_by_result_iterate_end;
1638 } action_by_result_iterate_end;
1639 }
1640 }
1641
1642 return ok;
1643}
1644
1645/**********************************************************************/
1648 bool autolock_settings(void)
1649{
1650 bool ok = TRUE;
1651
1652 if (num_role_units(L_BARBARIAN) == 0) {
1653 struct setting *pset = setting_by_name("barbarians");
1654
1655 log_normal(_("Disabling 'barbarians' setting for lack of suitable "
1656 "unit types."));
1657 setting_ruleset_lock_clear(pset);
1658 if (!setting_enum_set(pset, "DISABLED", NULL, NULL, 0)) {
1659 ok = FALSE;
1660 }
1661 setting_ruleset_lock_set(pset);
1662 }
1663
1664 return ok;
1665}
achievement_rule_name
const char * achievement_rule_name(struct achievement *pach)
Definition achievements.c:114
achievements.h
achievements_re_active_iterate
#define achievements_re_active_iterate(_p)
Definition achievements.h:74
achievements_re_active_iterate_end
#define achievements_re_active_iterate_end
Definition achievements.h:78
action_distance_inside_max
bool action_distance_inside_max(const struct action *action, const int distance)
Definition actions.c:1138
action_get_actor_kind
enum action_actor_kind action_get_actor_kind(const struct action *paction)
Definition actions.c:1063
action_auto_perf_slot_number
struct action_auto_perf * action_auto_perf_slot_number(const int num)
Definition actions.c:5658
action_enabler_suggest_repair
struct req_vec_problem * action_enabler_suggest_repair(const struct action_enabler *enabler)
Definition actions.c:1882
action_enabler_suggest_improvement
struct req_vec_problem * action_enabler_suggest_improvement(const struct action_enabler *enabler)
Definition actions.c:1948
action_rule_name
const char * action_rule_name(const struct action *action)
Definition actions.c:1181
action_id_rule_name
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1204
action_would_be_blocked_by
bool action_would_be_blocked_by(const struct action *blocked, const struct action *blocker)
Definition actions.c:1161
action_dice_roll_initial_odds
int action_dice_roll_initial_odds(const struct action *paction)
Definition actions.c:5310
action_get_target_kind
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1073
action_enablers_for_action
struct action_enabler_list * action_enablers_for_action(action_id action)
Definition actions.c:1519
actions.h
action_by_result_iterate
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:236
ACTION_DISTANCE_MAX
#define ACTION_DISTANCE_MAX
Definition actions.h:103
enabler_get_action
#define enabler_get_action(_enabler_)
Definition actions.h:177
ACTION_AUTO_MOVED_ADJ
#define ACTION_AUTO_MOVED_ADJ
Definition actions.h:366
action_auto_perf_actions_iterate_end
#define action_auto_perf_actions_iterate_end
Definition actions.h:357
action_by_number
static struct action * action_by_number(action_id act_id)
Definition actions.h:390
action_enabler_list_re_iterate_end
#define action_enabler_list_re_iterate_end
Definition actions.h:191
ACTION_DISTANCE_LAST_NON_SIGNAL
#define ACTION_DISTANCE_LAST_NON_SIGNAL
Definition actions.h:99
action_enabler_list_re_iterate
#define action_enabler_list_re_iterate(action_enabler_list, aenabler)
Definition actions.h:187
action_has_result
#define action_has_result(_act_, _res_)
Definition actions.h:175
action_by_result_iterate_end
#define action_by_result_iterate_end
Definition actions.h:240
action_auto_perf_actions_iterate
#define action_auto_perf_actions_iterate(_autoperf_, _act_id_)
Definition actions.h:354
action_iterate_end
#define action_iterate_end
Definition actions.h:209
action_has_result_safe
#define action_has_result_safe(paction, result)
Definition actions.h:418
action_iterate
#define action_iterate(_act_)
Definition actions.h:205
action_id_get_target_kind
#define action_id_get_target_kind(act_id)
Definition actions.h:407
ACTION_ODDS_PCT_DICE_ROLL_NA
#define ACTION_ODDS_PCT_DICE_ROLL_NA
Definition actions.h:669
actres_legal_target_kind
bool actres_legal_target_kind(enum action_result result, enum action_target_kind tgt_kind)
Definition actres.c:558
astr_free
void astr_free(struct astring *astr)
Definition astring.c:148
astring.h
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
city_style_rule_name
const char * city_style_rule_name(const int style)
Definition city.c:1757
city_styles
static const struct city struct citystyle * city_styles
Definition city.c:83
MAX_CITY_SIZE
#define MAX_CITY_SIZE
Definition city.h:106
incite_cost
char * incite_cost
Definition comments.c:74
MAX_LEN_CONTENT
#define MAX_LEN_CONTENT
Definition conn_types.h:32
deprecations.h
log_deprecation
#define log_deprecation(message,...)
Definition deprecations.h:35
disaster_rule_name
const char * disaster_rule_name(struct disaster_type *pdis)
Definition disaster.c:105
disaster_type_re_active_iterate
#define disaster_type_re_active_iterate(_p)
Definition disaster.h:93
disaster_type_re_active_iterate_end
#define disaster_type_re_active_iterate_end
Definition disaster.h:96
id
int int id
Definition editgui_g.h:28
reqs
struct @21::@22 reqs
iterate_effect_cache
bool iterate_effect_cache(iec_cb cb, void *data)
Definition effects.c:1323
get_potential_improvement_bonus
int get_potential_improvement_bonus(const struct impr_type *pimprove, const struct city *pcity, enum effect_type effect_type, const enum req_problem_type prob_type, bool consider_multipliers)
Definition effects.c:1204
effect_cumulative_max
int effect_cumulative_max(enum effect_type type, struct universal *unis, size_t n_unis)
Definition effects.c:388
effect_cumulative_min
int effect_cumulative_min(enum effect_type type, struct universal *for_uni)
Definition effects.c:424
effects.h
extra_has_flag
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:861
extra_rule_name
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
extra_type_list_iterate
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:165
is_extra_caused_by
#define is_extra_caused_by(e, c)
Definition extras.h:203
extra_index
#define extra_index(_e_)
Definition extras.h:183
extra_type_re_active_iterate_end
#define extra_type_re_active_iterate_end
Definition extras.h:329
extra_type_list_iterate_end
#define extra_type_list_iterate_end
Definition extras.h:167
extra_road_get
#define extra_road_get(_e_)
Definition extras.h:191
extra_type_re_active_iterate
#define extra_type_re_active_iterate(_p)
Definition extras.h:325
extra_type_by_cause_iterate_end
#define extra_type_by_cause_iterate_end
Definition extras.h:339
extra_type_by_cause_iterate
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
server_setting_id
int server_setting_id
Definition fc_types.h:1080
Tech_type_id
int Tech_type_id
Definition fc_types.h:381
ssetv
int ssetv
Definition fc_types.h:700
RPT_POSSIBLE
@ RPT_POSSIBLE
Definition fc_types.h:707
action_id
int action_id
Definition fc_types.h:393
MAX_NUM_TECH_LIST
#define MAX_NUM_TECH_LIST
Definition fc_types.h:44
_
#define _(String)
Definition fcintl.h:67
game
struct civ_game game
Definition game.c:62
game.h
government_rule_name
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
government.h
governments_re_active_iterate
#define governments_re_active_iterate(_p)
Definition government.h:125
governments_re_active_iterate_end
#define governments_re_active_iterate_end
Definition government.h:129
is_building_sellable
bool is_building_sellable(const struct impr_type *pimprove)
Definition improvement.c:1110
improvement_rule_name
const char * improvement_rule_name(const struct impr_type *pimprove)
Definition improvement.c:252
is_wonder
bool is_wonder(const struct impr_type *pimprove)
Definition improvement.c:343
is_great_wonder
bool is_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:772
improvement_has_flag
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
Definition improvement.c:383
improvement_name_translation
const char * improvement_name_translation(const struct impr_type *pimprove)
Definition improvement.c:243
improvement_re_active_iterate_end
#define improvement_re_active_iterate_end
Definition improvement.h:214
improvement_re_active_iterate
#define improvement_re_active_iterate(_p)
Definition improvement.h:210
B_LAST
#define B_LAST
Definition improvement.h:42
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
log_debug
#define log_debug(message,...)
Definition log.h:115
log_normal
#define log_normal(message,...)
Definition log.h:107
LOG_ERROR
@ LOG_ERROR
Definition log.h:30
LOG_WARN
@ LOG_WARN
Definition log.h:31
map.h
is_native_to_class
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:341
can_unit_type_transport
bool can_unit_type_transport(const struct unit_type *transporter, const struct unit_class *transported)
Definition movement.c:869
movement.h
nation_rule_name
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
nation_by_rule_name
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
nation_barbarian_type
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:211
nation.h
nations_re_active_iterate_end
#define nations_re_active_iterate_end
Definition nation.h:342
nations_re_active_iterate
#define nations_re_active_iterate(_pnat_)
Definition nation.h:339
player.h
req_to_fstring
const char * req_to_fstring(const struct requirement *req, struct astring *astr)
Definition requirements.c:1026
req_vec_vector_number
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
Definition requirements.c:6178
req_vec_suggest_repair
struct req_vec_problem * req_vec_suggest_repair(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
Definition requirements.c:6468
universal_rule_name
const char * universal_rule_name(const struct universal *psource)
Definition requirements.c:6800
req_vec_problem_free
void req_vec_problem_free(struct req_vec_problem *issue)
Definition requirements.c:6383
universal_type_rule_name
const char * universal_type_rule_name(const struct universal *psource)
Definition requirements.c:7313
is_req_unchanging
enum req_unchanging_status is_req_unchanging(const struct req_context *context, const struct requirement *req)
Definition requirements.c:5948
requirement_vector_iterate_end
#define requirement_vector_iterate_end
Definition requirements.h:94
requirement_vector_iterate
#define requirement_vector_iterate(req_vec, preq)
Definition requirements.h:92
REQUCH_HACK
@ REQUCH_HACK
Definition requirements.h:123
road_number
Road_type_id road_number(const struct road_type *proad)
Definition road.c:32
sanity_check_ruleset_data
bool sanity_check_ruleset_data(struct rscompat_info *compat)
Definition rssanity.c:853
sanity_check_req_vec
static bool sanity_check_req_vec(rs_conversion_logger logger, const struct requirement_vector *preqs, bool conjunctive, int max_tiles, const char *list_for)
Definition rssanity.c:493
sanity_check_server_setting_value_in_req
bool sanity_check_server_setting_value_in_req(ssetv ssetval)
Definition rssanity.c:143
req_base_effects_3_3
enum effect_type req_base_effects_3_3[]
Definition rssanity.c:51
req_base_effects
enum effect_type req_base_effects[]
Definition rssanity.c:43
sanity_check_req_set
static bool sanity_check_req_set(rs_conversion_logger logger, int reqs_of_type[], int local_reqs_of_type[], int tile_reqs_of_type[], struct requirement *preq, bool conjunctive, int max_tiles, const char *list_for)
Definition rssanity.c:256
sanity_check_boolean_effects
static bool sanity_check_boolean_effects(rs_conversion_logger logger)
Definition rssanity.c:801
sanity_check_setting_is_seen
static bool sanity_check_setting_is_seen(struct setting *pset)
Definition rssanity.c:107
sanity_check_req_individual
static bool sanity_check_req_individual(rs_conversion_logger logger, struct requirement *preq, const char *list_for)
Definition rssanity.c:170
rs_buildings
static bool rs_buildings(rs_conversion_logger logger)
Definition rssanity.c:754
sanity_check_metadata
static bool sanity_check_metadata(rs_conversion_logger logger)
Definition rssanity.c:60
autolock_settings
bool autolock_settings(void)
Definition rssanity.c:1648
rs_common_units
static bool rs_common_units(rs_conversion_logger logger)
Definition rssanity.c:700
autoadjust_ruleset_data
bool autoadjust_ruleset_data(void)
Definition rssanity.c:1551
rs_barbarian_units
static bool rs_barbarian_units(rs_conversion_logger logger)
Definition rssanity.c:628
effect_list_sanity_cb
static bool effect_list_sanity_cb(struct effect *peffect, void *data)
Definition rssanity.c:535
sanity_check_setting_is_game_rule
static bool sanity_check_setting_is_game_rule(struct setting *pset)
Definition rssanity.c:116
nation_has_initial_tech
static bool nation_has_initial_tech(struct nation_type *pnation, struct advance *tech)
Definition rssanity.c:78
rssanity.h
ruleload.h
rs_conversion_logger
void(* rs_conversion_logger)(const char *msg)
Definition ruleload.h:42
ruleset_error
#define ruleset_error(logger, level, format,...)
Definition ruleload.h:59
RSFORMAT_3_3
#define RSFORMAT_3_3
Definition ruleload.h:37
compat
static struct compatibility compat[]
Definition savecompat.c:112
server_setting_name_get
const char * server_setting_name_get(server_setting_id id)
Definition server_settings.c:40
server_setting_type_get
enum sset_type server_setting_type_get(server_setting_id id)
Definition server_settings.c:51
ssetv_setting_get
server_setting_id ssetv_setting_get(ssetv enc)
Definition server_settings.c:129
server_setting_exists
bool server_setting_exists(server_setting_id id)
Definition server_settings.c:62
setting_ruleset_lock_clear
void setting_ruleset_lock_clear(struct setting *pset)
Definition settings.c:4669
setting_by_name
struct setting * setting_by_name(const char *name)
Definition settings.c:3302
setting_by_number
struct setting * setting_by_number(int id)
Definition settings.c:3294
setting_category
enum sset_category setting_category(const struct setting *pset)
Definition settings.c:3371
setting_enum_set
bool setting_enum_set(struct setting *pset, const char *val, struct connection *caller, char *reject_msg, size_t reject_msg_len)
Definition settings.c:4015
setting_ruleset_lock_set
void setting_ruleset_lock_set(struct setting *pset)
Definition settings.c:4649
setting_is_visible_at_level
bool setting_is_visible_at_level(const struct setting *pset, enum cmdlevel plevel)
Definition settings.c:3489
settings.h
formats_match
bool formats_match(const char *format1, const char *format2)
Definition shared.c:2450
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
specialist_rule_name
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
specialist.h
specialist_type_re_active_iterate_end
#define specialist_type_re_active_iterate_end
Definition specialist.h:88
specialist_type_re_active_iterate
#define specialist_type_re_active_iterate(_p)
Definition specialist.h:83
action_auto_perf
Definition actions.h:316
action
Definition actions.h:106
advance
Definition tech.h:124
advance::require
struct advance * require[AR_SIZE]
Definition tech.h:132
astring
Definition astring.h:36
civ_game::control
struct packet_ruleset_control control
Definition game.h:83
civ_game::ruleset_summary
char * ruleset_summary
Definition game.h:84
civ_game::global_init_techs
int global_init_techs[MAX_NUM_TECH_LIST]
Definition game.h:108
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::embedded_nations
char ** embedded_nations
Definition game.h:283
civ_game::ruledit
struct civ_game::@31::@35::@40 ruledit
civ_game::server
struct civ_game::@31::@35 server
civ_game::embedded_nations_count
size_t embedded_nations_count
Definition game.h:284
civ_game::rgame
struct civ_game::@30 rgame
civ_game::calendar
struct packet_calendar_info calendar
Definition game.h:90
civ_game::default_government
struct government * default_government
Definition game.h:93
civ_game::government_during_revolution
struct government * government_during_revolution
Definition game.h:94
compatibility::version
int version
Definition savecompat.c:95
effect
Definition effects.h:40
els_data
Definition rssanity.c:525
els_data::logger
rs_conversion_logger logger
Definition rssanity.c:529
impr_type
Definition improvement.h:50
nation_type
Definition nation.h:98
nation_type::init_techs
int init_techs[MAX_NUM_TECH_LIST]
Definition nation.h:122
packet_calendar_info::calendar_fragments
int calendar_fragments
Definition packets_gen.h:263
packet_game_info::free_tech_method
enum free_tech_method free_tech_method
Definition packets_gen.h:237
packet_game_info::diplchance_initial_odds
bv_actions diplchance_initial_odds
Definition packets_gen.h:154
packet_game_info::tech_cost_style
enum tech_cost_style tech_cost_style
Definition packets_gen.h:232
packet_ruleset_control::num_unit_types
int num_unit_types
Definition packets_gen.h:1459
packet_ruleset_control::num_city_styles
int num_city_styles
Definition packets_gen.h:1475
req_vec_problem
Definition requirements.h:295
requirement
Definition requirements.h:81
road_type
Definition road.h:71
rscompat_info
Definition rscompat.h:30
setting
Definition settings.c:92
unit_type
Definition unittype.h:507
unit_type::obsoleted_by
const struct unit_type * obsoleted_by
Definition unittype.h:536
style_rule_name
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
basic_city_style_for_style
int basic_city_style_for_style(struct nation_style *pstyle)
Definition style.c:210
music_styles_re_active_iterate_end
#define music_styles_re_active_iterate_end
Definition style.h:88
music_styles_re_active_iterate
#define music_styles_re_active_iterate(_p)
Definition style.h:85
styles_re_active_iterate_end
#define styles_re_active_iterate_end
Definition style.h:60
styles_re_active_iterate
#define styles_re_active_iterate(_p)
Definition style.h:56
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
advance_by_number
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
advance_requires
struct advance * advance_requires(const struct advance *padvance, enum tech_req require)
Definition tech.c:136
valid_advance_by_number
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
advance_rule_name
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
advance_number
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
tech.h
advance_re_active_iterate
#define advance_re_active_iterate(_p)
Definition tech.h:282
A_NEVER
#define A_NEVER
Definition tech.h:51
advance_req_iterate
#define advance_req_iterate(_goal, _padvance)
Definition tech.h:300
AR_ROOT
@ AR_ROOT
Definition tech.h:113
AR_ONE
@ AR_ONE
Definition tech.h:111
AR_SIZE
@ AR_SIZE
Definition tech.h:114
advance_re_active_iterate_end
#define advance_re_active_iterate_end
Definition tech.h:286
advance_req_iterate_end
#define advance_req_iterate_end
Definition tech.h:304
A_NONE
#define A_NONE
Definition tech.h:43
A_LAST
#define A_LAST
Definition tech.h:45
terrain_rule_name
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
terrain_re_active_iterate_end
#define terrain_re_active_iterate_end
Definition terrain.h:281
is_ocean
#define is_ocean(pterrain)
Definition terrain.h:194
terrain_re_active_iterate
#define terrain_re_active_iterate(_p)
Definition terrain.h:277
terrain_resources_iterate_end
#define terrain_resources_iterate_end
Definition terrain.h:294
terrain_resources_iterate
#define terrain_resources_iterate(pterrain, _res, _freq)
Definition terrain.h:285
goods_rule_name
const char * goods_rule_name(struct goods_type *pgood)
Definition traderoutes.c:633
goods_type_re_active_iterate_end
#define goods_type_re_active_iterate_end
Definition traderoutes.h:244
goods_type_re_active_iterate
#define goods_type_re_active_iterate(_p)
Definition traderoutes.h:240
utype_is_cityfounder
bool utype_is_cityfounder(const struct unit_type *utype)
Definition unittype.c:2951
get_role_unit
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2253
utype_has_role
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:199
num_role_units
int num_role_units(int role)
Definition unittype.c:2203
utype_rule_name
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1578
uclass_rule_name
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1641
uclass_has_flag
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:773
unit_type_re_active_iterate
#define unit_type_re_active_iterate(_p)
Definition unittype.h:871
utype_class
#define utype_class(_t_)
Definition unittype.h:756
unit_class_re_active_iterate_end
#define unit_class_re_active_iterate_end
Definition unittype.h:928
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
unit_class_re_active_iterate
#define unit_class_re_active_iterate(_p)
Definition unittype.h:924
UNIT_MAX_PARADROP_RANGE
#define UNIT_MAX_PARADROP_RANGE
Definition unittype.h:56
uclass_index
#define uclass_index(_c_)
Definition unittype.h:749
unit_type_re_active_iterate_end
#define unit_type_re_active_iterate_end
Definition unittype.h:875