<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40193 >

 $subject

 For S2_2 and TRUNK


 - ML

diff -Nurd -X.diff_ignore freeciv/server/ruleset.c freeciv/server/ruleset.c
--- freeciv/server/ruleset.c	2008-04-01 22:40:44.000000000 +0300
+++ freeciv/server/ruleset.c	2008-04-06 22:39:31.000000000 +0300
@@ -3670,6 +3670,78 @@
 }
 
 /**************************************************************************
+  Helper function for sanity_check_req_list() and sanity_check_req_vec()
+**************************************************************************/
+static bool sanity_check_req_set(int reqs_of_type[], struct requirement *preq,
+                                 int max_tiles, const char *list_for)
+{
+  int rc;
+
+  assert(preq->source.kind >= 0 && preq->source.kind < VUT_LAST);
+
+  /* Add to counter */
+  reqs_of_type[preq->source.kind]++;
+  rc = reqs_of_type[preq->source.kind];
+
+  if (rc > 1) {
+    /* Multiple requirements of the same type */
+    switch (preq->source.kind) {
+     case VUT_GOVERNMENT:
+     case VUT_NATION:
+     case VUT_UTYPE:
+     case VUT_UCLASS:
+     case VUT_OTYPE:
+     case VUT_SPECIALIST:
+     case VUT_MINSIZE: /* Breaks nothing, but has no sense either */
+     case VUT_AI_LEVEL:
+     case VUT_TERRAINCLASS:
+       /* There can be only one requirement of these types (with current
+        * range limitations)
+        * Requirements might be identical, but we consider multiple
+        * declarations error anyway. */
+
+       freelog(LOG_ERROR,
+               "%s: Requirement list has multiple %s requirements",
+               list_for,
+               universal_type_rule_name(&preq->source));
+       return FALSE;
+       break;
+
+     case VUT_SPECIAL:
+     case VUT_TERRAIN:
+       /* There can be only up to max_tiles requirements of these types */
+       if (max_tiles != 1 && rc > max_tiles) {
+         freelog(LOG_ERROR,
+                 "%s: Requirement list has more %s requirements than "
+                 "can ever be fullfilled.",
+                 list_for,
+                 universal_type_rule_name(&preq->source));
+         return FALSE;
+       }
+       break;
+
+     case VUT_NONE:
+     case VUT_ADVANCE:
+     case VUT_IMPROVEMENT:
+     case VUT_UTFLAG:
+     case VUT_UCFLAG:
+       /* Can have multiple requirements of these types */
+       break;
+     case VUT_LAST:
+       /* Should never be in requirement vector */
+       assert(FALSE);
+       return FALSE;
+       break;
+       /* No default handling here, as we want compiler warning
+        * if new requirement type is added to enum and it's not handled
+        * here. */
+    }
+  }
+
+  return TRUE;
+}
+
+/**************************************************************************
   Check if requirement list is free of conflicting requirements.
   max_tiles is number of tiles that can provide requirement. Value -1
   disables checking based on number of tiles.
@@ -3692,75 +3764,38 @@
   memset(reqs_of_type, 0, sizeof(reqs_of_type));
 
   requirement_list_iterate(preqs, preq) {
-    int rc;
-
-    assert(preq->source.kind >= 0 && preq->source.kind < VUT_LAST);
-
-    /* Add to counter */
-    reqs_of_type[preq->source.kind]++;
-    rc = reqs_of_type[preq->source.kind];
+    if (!sanity_check_req_set(reqs_of_type, preq, max_tiles, list_for)) {
+      return FALSE;
+    }
+  } requirement_list_iterate_end;
 
-    if (rc > 1) {
-      /* Multiple requirements of same the type */
-      switch (preq->source.kind) {
-       case VUT_GOVERNMENT:
-       case VUT_NATION:
-       case VUT_UTYPE:
-       case VUT_UCLASS:
-       case VUT_OTYPE:
-       case VUT_SPECIALIST:
-       case VUT_MINSIZE: /* Breaks nothing, but has no sense either */
-       case VUT_AI_LEVEL:
-       case VUT_TERRAINCLASS:
-         /* There can be only one requirement of these types (with current
-          * range limitations)
-          * Requirements might be identical, but we consider multiple
-          * declarations error anyway. */
+  return TRUE;
+}
 
-         freelog(LOG_ERROR,
-                 "%s: Requirement list has multiple %s requirements",
-                 list_for,
-                 universal_type_rule_name(&preq->source));
-         return FALSE;
-         break;
+/**************************************************************************
+  Requirement vector version of requirement sanity checking. See
+  retuirement list version for comments.
+**************************************************************************/
+static bool sanity_check_req_vec(const struct requirement_vector *preqs,
+                                 int max_tiles,
+                                 const char *list_for)
+{
+  int reqs_of_type[VUT_LAST];
 
-       case VUT_SPECIAL:
-       case VUT_TERRAIN:
-         /* There can be only up to max_tiles requirements of these types */
-         if (max_tiles != 1 && rc > max_tiles) {
-           freelog(LOG_ERROR,
-                   "%s: Requirement list has more %s requirements than "
-                   "can ever be fullfilled.",
-                   list_for,
-                   universal_type_rule_name(&preq->source));
-           return FALSE;
-         }
-         break;
+  /* Initialize requirement counters */
+  memset(reqs_of_type, 0, sizeof(reqs_of_type));
 
-       case VUT_NONE:
-       case VUT_ADVANCE:
-       case VUT_IMPROVEMENT:
-       case VUT_UTFLAG:
-       case VUT_UCFLAG:
-         /* Can have multiple requirements of these types */
-         break;
-       case VUT_LAST:
-         /* Should never be in requirement vector */
-         assert(FALSE);
-         return FALSE;
-         break;
-       /* No default handling here, as we want compiler warning
-        * if new requirement type is added to enum and it's not handled
-        * here. */
-      }
+  requirement_vector_iterate(preqs, preq) {
+    if (!sanity_check_req_set(reqs_of_type, preq, max_tiles, list_for)) {
+      return FALSE;
     }
-  } requirement_list_iterate_end;
+  } requirement_vector_iterate_end;
 
   return TRUE;
 }
 
 /**************************************************************************
-  Check that requirement vector and negated requirements vector do not have
+  Check that requirement list and negated requirements list do not have
   confliciting requirements.
 
   Returns TRUE iff everything ok.
@@ -3797,7 +3832,7 @@
 /**************************************************************************
   Sanity check callback for iterating effects cache.
 **************************************************************************/
-static bool effect_sanity_cb(const struct effect *peffect)
+static bool effect_list_sanity_cb(const struct effect *peffect)
 {
   int one_tile = -1; /* TODO: Determine correct value from effect.
                       *       -1 disables checking */
@@ -3816,6 +3851,10 @@
 static bool sanity_check_ruleset_data(void)
 {
   int num_utypes;
+  int i;
+  bool ok = TRUE; /* Store failures to variable instead of returning
+                   * immediately so all errors get printed, not just first
+                   * one. */
 
   /* Check that all players can have their initial techs */
   nations_iterate(pnation) {
@@ -3857,6 +3896,7 @@
                       "Tech %s does not exist, but is tech for %s.",
                       advance_rule_name(advance_by_number(tech)),
                       nation_rule_name(pnation));
+        ok = FALSE;
       }
       if (advance_by_number(A_NONE) != a->require[AR_ROOT]
           && !nation_has_initial_tech(pnation, a->require[AR_ROOT])) {
@@ -3866,6 +3906,7 @@
                       "no root_req for it.",
                       advance_rule_name(a),
                       nation_rule_name(pnation));
+        ok = FALSE;
       }
     }
   } nations_iterate_end;
@@ -3883,19 +3924,56 @@
         ruleset_error(LOG_FATAL,
                       "There seems to be obsoleted_by loop in update "
                       "chain that starts from %s", utype_rule_name(putype));
+        ok = FALSE;
       }
     }
   } unit_type_iterate_end;
 
-  /* Check requirement lists against conflicting requirements */
-  /* Effects */
-  if (!iterate_effect_cache(effect_sanity_cb)) {
+  /* Check requirement sets against conflicting requirements.
+   * Effects use requirement lists */
+  if (!iterate_effect_cache(effect_list_sanity_cb)) {
     ruleset_error(LOG_FATAL, "Effects have conflicting requirements!");
+    ok = FALSE;
   }
-  /* TODO: Check other requirement lists also
-   *       (Governments, Buildings, Specialists, City styles)
-   *       These use currently requirement_vector, when effects
-   *       (and sanity checking) use requirement_list. */
 
-  return TRUE;
+  /* Others use requirement vectors
+   * Buildings */
+  improvement_iterate(pimprove) {
+    if (!sanity_check_req_vec(&pimprove->reqs, -1,
+                              improvement_rule_name(pimprove))) {
+      ruleset_error(LOG_FATAL, "Buildings have conflicting requirements!");
+      ok = FALSE;
+    }
+  } improvement_iterate_end;
+
+  /* Governments */
+  government_iterate(pgov) {
+    if (!sanity_check_req_vec(&pgov->reqs, -1,
+                              government_rule_name(pgov))) {
+      ruleset_error(LOG_FATAL, "Governments have conflicting requirements!");
+      ok = FALSE;
+    }
+  } government_iterate_end;
+
+  /* Specialists */
+  specialist_type_iterate(sp) {
+    struct specialist *psp = specialist_by_number(sp);
+
+    if (!sanity_check_req_vec(&psp->reqs, -1,
+                              specialist_rule_name(psp))) {
+      ruleset_error(LOG_FATAL, "Specialists have conflicting requirements!");
+      ok = FALSE;
+    }
+  } specialist_type_iterate_end;
+
+  /* City styles */
+  for (i = 0; i < game.control.styles_count; i++) {
+    if (!sanity_check_req_vec(&city_styles[i].reqs, -1,
+                              city_style_rule_name(i))) {
+      ruleset_error(LOG_FATAL, "City styles have conflicting requirements!");
+      ok = FALSE;
+    }
+  }
+
+  return ok;
 }
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to