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

 Applies on top of #33876.


 - ML

diff -Nurd -X.diff_ignore freeciv/common/base.c freeciv/common/base.c
--- freeciv/common/base.c	2007-01-19 13:50:26.000000000 +0200
+++ freeciv/common/base.c	2007-01-19 13:57:54.000000000 +0200
@@ -19,52 +19,59 @@
 
 #include "base.h"
 
+static struct base_type base_types[BASE_TYPE_LAST];
+
+static const char *base_type_flag_names[] = {
+  "NoAggressive", "DefenseBonus", "NoStackDeath", "Watchtower",
+  "ClaimTerritory", "DiplomatDefense", "Refuel", "NoHPLoss",
+  "AttackUnreachable", "ParadropFrom"
+};
+
 /****************************************************************************
   Check if base provides effect
 ****************************************************************************/
-bool base_flag(Base_type_id base_type, enum base_flag_id flag)
+bool base_flag(const struct base_type *pbase, enum base_flag_id flag)
 {
-  switch(base_type) {
-  case BASE_TYPE_1:
-    /* Fortress */
-    switch(flag) {
-    case BF_NOT_AGGRESSIVE:
-    case BF_DEFENSE_BONUS:
-    case BF_WATCHTOWER:
-    case BF_CLAIM_TERRITORY:
-    case BF_NO_STACK_DEATH:
-    case BF_DIPLOMAT_DEFENSE:
-      return TRUE;
-
-    case BF_REFUEL:
-    case BF_NO_HP_LOSS:
-    case BF_ATTACK_UNREACHABLE:
-    case BF_PARADROP_FROM:
-    case BF_LAST:
-      return FALSE;
-    }
-    break;
+  return BV_ISSET(pbase->flags, flag);
+}
 
-  case BASE_TYPE_2:
-    /* Airbase */
-    switch(flag) {
-    case BF_NO_STACK_DEATH:
-    case BF_DIPLOMAT_DEFENSE:
-    case BF_REFUEL:
-    case BF_NO_HP_LOSS:
-    case BF_ATTACK_UNREACHABLE:
-    case BF_PARADROP_FROM:
-      return TRUE;
+/**************************************************************************
+  Convert base flag names to enum; case insensitive;
+  returns BF_LAST if can't match.
+**************************************************************************/
+enum base_flag_id base_flag_from_str(const char *s)
+{
+  enum base_flag_id i;
 
-    case BF_NOT_AGGRESSIVE:
-    case BF_DEFENSE_BONUS:
-    case BF_WATCHTOWER:
-    case BF_CLAIM_TERRITORY:
-    case BF_LAST:
-      return FALSE;
+  assert(ARRAY_SIZE(base_type_flag_names) == BF_LAST);
+  
+  for(i = 0; i < BF_LAST; i++) {
+    if (mystrcasecmp(base_type_flag_names[i], s)==0) {
+      return i;
     }
-    break;
   }
+  return BF_LAST;
+}
 
-  return FALSE;
+/****************************************************************************
+  Returns base type structure for an ID value.
+****************************************************************************/
+struct base_type *base_type_get_by_id(Base_type_id id)
+{
+  if (id < 0 || id >= BASE_TYPE_LAST) {
+    return NULL;
+  }
+  return &base_types[id];
+}
+
+/****************************************************************************
+  Inialize base_type structures.
+****************************************************************************/
+void base_types_init(void)
+{
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE(base_types); i++) {
+    base_types[i].id = i;
+  }
 }
diff -Nurd -X.diff_ignore freeciv/common/base.h freeciv/common/base.h
--- freeciv/common/base.h	2007-01-19 13:50:26.000000000 +0200
+++ freeciv/common/base.h	2007-01-19 13:46:22.000000000 +0200
@@ -15,7 +15,7 @@
 
 #include "fc_types.h"
 
-enum base_type_id { BASE_TYPE_1, BASE_TYPE_2 };
+enum base_type_id { BASE_TYPE_1 = 0, BASE_TYPE_2, BASE_TYPE_LAST };
 
 typedef enum base_type_id Base_type_id;
 
@@ -34,6 +34,31 @@
   BF_LAST                /* This has to be last */
 };
 
-bool base_flag(Base_type_id base_type, enum base_flag_id flag);
+BV_DEFINE(bv_base_flags, BF_LAST);
+
+struct base_type {
+  const char *name;
+  char name_orig[MAX_LEN_NAME];
+  int id;
+  bv_base_flags flags;
+};
+
+bool base_flag(const struct base_type *pbase, enum base_flag_id flag);
+enum base_flag_id base_flag_from_str(const char *s);
+struct base_type *base_type_get_by_id(Base_type_id id);
+
+void base_types_init(void);
+
+#define base_type_iterate(pbase)                                            \
+{                                                                           \
+  int _index;                                                               \
+                                                                            \
+  for (_index = 0; _index < BASE_TYPE_LAST; _index++) {                     \
+    struct base_type *pbase = base_type_get_by_id(_index);
+
+#define base_type_iterate_end                                               \
+  }                                                                         \
+}
+
 
 #endif  /* FC__BASE_H */
diff -Nurd -X.diff_ignore freeciv/common/game.c freeciv/common/game.c
--- freeciv/common/game.c	2007-01-13 03:18:47.000000000 +0200
+++ freeciv/common/game.c	2007-01-19 13:32:04.000000000 +0200
@@ -17,6 +17,7 @@
 
 #include <assert.h>
 
+#include "base.h"
 #include "capstr.h"
 #include "city.h"
 #include "cm.h"
@@ -284,6 +285,7 @@
   init_our_capability();    
   map_init();
   terrains_init();
+  base_types_init();
   improvements_init();
   techs_init();
   unit_classes_init();
diff -Nurd -X.diff_ignore freeciv/common/tile.c freeciv/common/tile.c
--- freeciv/common/tile.c	2007-01-19 13:50:26.000000000 +0200
+++ freeciv/common/tile.c	2007-01-19 13:47:49.000000000 +0200
@@ -104,9 +104,9 @@
 bool tile_has_base_flag(const struct tile *ptile, enum base_flag_id flag)
 {
   return (tile_has_special(ptile, S_FORTRESS)
-          && base_flag(BASE_TYPE_1, flag))
+          && base_flag(base_type_get_by_id(BASE_TYPE_1), flag))
     || (tile_has_special(ptile, S_AIRBASE)
-        && base_flag(BASE_TYPE_2, flag));
+        && base_flag(base_type_get_by_id(BASE_TYPE_2), flag));
 }
 
 /****************************************************************************
diff -Nurd -X.diff_ignore freeciv/data/civ1/terrain.ruleset freeciv/data/civ1/terrain.ruleset
--- freeciv/data/civ1/terrain.ruleset	2006-07-17 23:56:23.000000000 +0300
+++ freeciv/data/civ1/terrain.ruleset	2007-01-19 13:53:40.000000000 +0200
@@ -592,3 +592,28 @@
 graphic_alt = "-"
 identifier  = "S"
 food        = 2
+
+; Below has to be definition for exactly two base types
+; Many places (including terrain fortress_time/airbase_time)
+; refer first one as fortress and second one as airbase.
+;
+; name                    = Name of the base type
+; flags
+;   - "NoAggressive"      = Units inside are not considered aggressive
+;   - "DefenseBonus"      = Units inside gain defense bonus
+;   - "NoStackDeath"      = Units inside do not die all at once when attacked
+;   - "Watchtower"        = Units inside see further if required tech known
+;   - "ClaimTerritory"    = Base will claim land ownership
+;   - "DiplomatDefense"   = Diplomats inside get bonus to diplomatic defense
+;   - "Refuel"            = Units can refuel at base
+;   - "NoHPLoss"          = Units inside avoid HP loss over time
+;   - "AttackUnreachable" = Unreachable units inside can be attacked
+;   - "ParadropFrom"      = Paradrop can be initiated from base
+
+[base_fortress]
+name        = _("Fortress")
+flags       = "NoAggressive", "DefenseBonus", "Watchtower", "ClaimTerritory", "NoStackDeath", "DiplomatDefense"
+
+[base_airbase]
+name        = _("Airbase")
+flags       = "NoStackDeath", "DiplomatDefense", "Refuel", "NoHPLoss", "AttackUnreachable", "ParadropFrom"
diff -Nurd -X.diff_ignore freeciv/data/civ2/terrain.ruleset freeciv/data/civ2/terrain.ruleset
--- freeciv/data/civ2/terrain.ruleset	2006-07-17 23:56:23.000000000 +0300
+++ freeciv/data/civ2/terrain.ruleset	2007-01-19 13:53:32.000000000 +0200
@@ -684,3 +684,28 @@
 food        = 1
 trade       = 3
 identifier  = "u"
+
+; Below has to be definition for exactly two base types
+; Many places (including terrain fortress_time/airbase_time)
+; refer first one as fortress and second one as airbase.
+;
+; name                    = Name of the base type
+; flags
+;   - "NoAggressive"      = Units inside are not considered aggressive
+;   - "DefenseBonus"      = Units inside gain defense bonus
+;   - "NoStackDeath"      = Units inside do not die all at once when attacked
+;   - "Watchtower"        = Units inside see further if required tech known
+;   - "ClaimTerritory"    = Base will claim land ownership
+;   - "DiplomatDefense"   = Diplomats inside get bonus to diplomatic defense
+;   - "Refuel"            = Units can refuel at base
+;   - "NoHPLoss"          = Units inside avoid HP loss over time
+;   - "AttackUnreachable" = Unreachable units inside can be attacked
+;   - "ParadropFrom"      = Paradrop can be initiated from base
+
+[base_fortress]
+name        = _("Fortress")
+flags       = "NoAggressive", "DefenseBonus", "Watchtower", "ClaimTerritory", "NoStackDeath", "DiplomatDefense"
+
+[base_airbase]
+name        = _("Airbase")
+flags       = "NoStackDeath", "DiplomatDefense", "Refuel", "NoHPLoss", "AttackUnreachable", "ParadropFrom"
diff -Nurd -X.diff_ignore freeciv/data/default/terrain.ruleset freeciv/data/default/terrain.ruleset
--- freeciv/data/default/terrain.ruleset	2006-07-17 23:56:23.000000000 +0300
+++ freeciv/data/default/terrain.ruleset	2007-01-19 13:53:23.000000000 +0200
@@ -753,3 +753,28 @@
 food        = 1
 trade       = 3
 identifier  = "u"
+
+; Below has to be definition for exactly two base types
+; Many places (including terrain fortress_time/airbase_time)
+; refer first one as fortress and second one as airbase.
+;
+; name                    = Name of the base type
+; flags
+;   - "NoAggressive"      = Units inside are not considered aggressive
+;   - "DefenseBonus"      = Units inside gain defense bonus
+;   - "NoStackDeath"      = Units inside do not die all at once when attacked
+;   - "Watchtower"        = Units inside see further if required tech known
+;   - "ClaimTerritory"    = Base will claim land ownership
+;   - "DiplomatDefense"   = Diplomats inside get bonus to diplomatic defense
+;   - "Refuel"            = Units can refuel at base
+;   - "NoHPLoss"          = Units inside avoid HP loss over time
+;   - "AttackUnreachable" = Unreachable units inside can be attacked
+;   - "ParadropFrom"      = Paradrop can be initiated from base
+
+[base_fortress]
+name        = _("Fortress")
+flags       = "NoAggressive", "DefenseBonus", "Watchtower", "ClaimTerritory", "NoStackDeath", "DiplomatDefense"
+
+[base_airbase]
+name        = _("Airbase")
+flags       = "NoStackDeath", "DiplomatDefense", "Refuel", "NoHPLoss", "AttackUnreachable", "ParadropFrom"
diff -Nurd -X.diff_ignore freeciv/server/ruleset.c freeciv/server/ruleset.c
--- freeciv/server/ruleset.c	2007-01-19 13:03:48.000000000 +0200
+++ freeciv/server/ruleset.c	2007-01-19 13:57:17.000000000 +0200
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "base.h"
 #include "capability.h"
 #include "city.h"
 #include "fcintl.h"
@@ -1515,6 +1516,22 @@
 
   free(sec);
 
+  sec = secfile_get_secnames_prefix(file, "base_", &nval);
+
+  if (nval != BASE_TYPE_LAST) {
+    freelog(LOG_ERROR, "Ruleset has to define exactly %d base types (%s)",
+            BASE_TYPE_LAST, filename);
+    exit(EXIT_FAILURE);
+  }
+
+  base_type_iterate(pbase) {
+    char *name;
+
+    name = secfile_lookup_str(file, "%s.name", sec[pbase->id]);
+    name_strlcpy(pbase->name_orig, name);
+  } base_type_iterate_end;
+
+  free(sec);
 }
 
 /**************************************************************************
@@ -1524,7 +1541,7 @@
 {
   char *datafile_options;
   int nval;
-  char **tsec, **rsec, **res;
+  char **tsec, **rsec, **bsec, **res;
   int j;
   const char *filename = secfile_filename(file);
 
@@ -1738,6 +1755,7 @@
 
     pterrain->helptext = lookup_helptext(file, tsec[i]);
   } terrain_type_iterate_end;
+  free(tsec);
 
   rsec = secfile_get_secnames_prefix(file, "resource_", &nval);
   resource_type_iterate(presource) {
@@ -1771,9 +1789,37 @@
       }
     }
   } resource_type_iterate_end;
-  free(tsec);
   free(rsec);
 
+  bsec = secfile_get_secnames_prefix(file, "base_", &nval);
+  {
+    base_type_iterate(pbase) {
+      char **slist;
+      int j;
+
+      pbase->name = Q_(pbase->name_orig);
+
+      slist = secfile_lookup_str_vec(file, &nval, "%s.flags", bsec[pbase->id]);
+      BV_CLR_ALL(pbase->flags);
+      for (j = 0; j < nval; j++) {
+        const char *sval = slist[j];
+        enum base_flag_id flag = base_flag_from_str(sval);
+
+        if (flag == BF_LAST) {
+          /* TRANS: message for an obscure ruleset error. */
+          freelog(LOG_FATAL, _("Base %s has unknown flag %s"),
+                  pbase->name, sval);
+          exit(EXIT_FAILURE);
+        } else {
+          BV_SET(pbase->flags, flag);
+        }
+      }
+
+      free(slist);
+    } base_type_iterate_end;
+  }
+  free(bsec);
+
   section_file_check_unused(file, filename);
   section_file_free(file);
 }
diff -Nurd -X.diff_ignore freeciv/server/unittools.c freeciv/server/unittools.c
--- freeciv/server/unittools.c	2007-01-19 13:50:26.000000000 +0200
+++ freeciv/server/unittools.c	2007-01-19 13:49:05.000000000 +0200
@@ -1254,9 +1254,9 @@
   if ((is_allied_city_tile(ptile, pplayer)
        && !is_non_allied_unit_tile(ptile, pplayer))
       || (((contains_special(plrtile->special, S_FORTRESS)
-            && base_flag(BASE_TYPE_1, BF_REFUEL))
+            && base_flag(base_type_get_by_id(BASE_TYPE_1), BF_REFUEL))
            || (contains_special(plrtile->special, S_AIRBASE)
-               && base_flag(BASE_TYPE_2, BF_REFUEL)))
+               && base_flag(base_type_get_by_id(BASE_TYPE_2), BF_REFUEL)))
 	  && !is_non_allied_unit_tile(ptile, pplayer)))
     return TRUE;
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to