Freeciv-3.2: /fast/freeciv/nightly/S3_2/server/rssanity.c Source File

Freeciv-3.2

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