Freeciv-3.1: /fast/freeciv/nightly/S3_1/server/rssanity.c Source File

Freeciv-3.1

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