<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
[email protected]
https://mail.gna.org/listinfo/freeciv-dev