? gen_capab.diff Index: common/registry.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/registry.c,v retrieving revision 1.34 diff -u -r1.34 registry.c --- common/registry.c 2001/08/13 15:13:35 1.34 +++ common/registry.c 2001/12/05 17:33:14 @@ -717,13 +717,13 @@ if(!(pentry=section_file_lookup_internal(my_section_file, buf))) { freelog(LOG_FATAL, "sectionfile %s doesn't contain a '%s' entry", secfile_filename(my_section_file), buf); - exit(1); + exit(0); } if(!pentry->svalue) { freelog(LOG_FATAL, "sectionfile %s entry '%s' doesn't contain a string", secfile_filename(my_section_file), buf); - exit(1); + exit(0); } return pentry->svalue; Index: common/unittype.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/unittype.c,v retrieving revision 1.8 diff -u -r1.8 unittype.c --- common/unittype.c 2001/09/15 15:31:25 1.8 +++ common/unittype.c 2001/12/05 17:33:15 @@ -30,11 +30,14 @@ #include "unittype.h" -struct unit_type unit_types[U_LAST]; -/* the unit_types array is now setup in: - server/ruleset.c (for the server) - client/packhand.c (for the client) +/** + * The unit_types array is now setup in: + * */ +struct unit_type unit_types[U_LAST]; static const char *move_type_names[] = { "Land", "Sea", "Heli", "Air" @@ -63,6 +66,67 @@ "Sea" }; +/* + * unit type capability categories + * This section contains string declarators for flag values + * and categories. + */ +static const char *utype_category_names[] = { + "capab_move", + "capab_class", + "capab_combat", + "capab_build", + "capab_improve", + "capab_intel" +}; + +/* + * This structure is used to maintain a mapping between + * configured flag name and the + */ +struct _named_bit_value +{ + const char *name; /* name of flag */ + unsigned value; /* flag value */ +}; + +/* + * unit type capability flag values + */ +static struct _named_bit_value utype_flag_values[]= { + { "move_land", CAPAB_MOVE_LAND }, + { "move_sea", CAPAB_MOVE_SEA }, + { "move_hover", CAPAB_MOVE_HOVER }, + { "move_ranged", CAPAB_MOVE_RANGED }, + { "move_orbit", CAPAB_MOVE_ORBIT }, + { "pikemen", CAPAB_PIKEMEN }, + { "horse", CAPAB_HORSE }, + { "attack_melee", CAPAB_ATTACK_MELEE }, + { "attack_bombard", CAPAB_ATTACK_BOMBARD }, + { "attack_bomb", CAPAB_ATTACK_BOMB }, + { "attack_nuke", CAPAB_ATTACK_NUKE }, + { "transport_any", CAPAB_TRANSPORT_ANY }, + { "build_city", CAPAB_BUILD_CITY }, + { "build_fortress", CAPAB_BUILD_FORTRESS }, + { "build_airbase", CAPAB_BUILD_AIRBASE }, + { "build_colony", CAPAB_BUILD_COLONY }, + { "improve_irrigate", CAPAB_IMPROVE_IRRIGATE }, + { "improve_mine", CAPAB_IMPROVE_MINE }, + { "improve_road", CAPAB_IMPROVE_ROAD }, + { "improve_rail", CAPAB_IMPROVE_RAIL }, + { "intel_embassy", CAPAB_INTEL_EMBASSY }, + { "intel_bribe", CAPAB_INTEL_BRIBE }, + { "intel_sabotage", CAPAB_INTEL_SABOTAGE }, + { "intel_steal", CAPAB_INTEL_STEAL }, + { "intel_incite", CAPAB_INTEL_INCITE }, + { "intel_move", CAPAB_INTEL_MOVE }, + { "intel_poison", CAPAB_INTEL_MOVE }, + + /* ... */ + + { 0, 0 } +}; + /************************************************************************** Returns 1 if the unit_type "exists" in this game, 0 otherwise. A unit_type doesn't exist if one of: @@ -276,15 +340,15 @@ if(count==1) { char *and_str = _(" and "); - astr_minsize(&astr,astr.n+strlen(and_str)); - strcat(astr.str, and_str); + astr_minsize(&astr,astr.n+strlen(and_str)); + strcat(astr.str, and_str); } else { - if(count != 0) { - astr_minsize(&astr,astr.n+strlen(", ")); - strcat(astr.str,", "); - } - else return astr.str; + if(count != 0) { + astr_minsize(&astr,astr.n+strlen(", ")); + strcat(astr.str,", "); + } + else return astr.str; } } } @@ -438,7 +502,7 @@ return 0; while(unit_type_exists((id = unit_types[id].obsoleted_by))) if (can_player_build_unit_direct(p, id)) - return 0; + return 0; return 1; } @@ -453,7 +517,7 @@ return 0; while(unit_type_exists((id = unit_types[id].obsoleted_by))) if (can_player_build_unit_direct(p, id)) - return 0; + return 0; return 1; } @@ -562,3 +626,88 @@ return U_LAST; } + +/*@ + * @brief Get the name of a flag category. + * + * This method is used to get the configurable name + * of a unit type. This is called from the server + * ruleset configuration to assign flag values to + * categories. + * + * @param category The category identifier. + * @return A pointer to the string containing the category + * name. + */ +const char * +utype_get_category_name( enum utype_category category ) +{ + /* make sure we have a null string on invalid an category. */ + if( ( category < 0 ) || ( category >= CAT_LAST ) ) { + return 0; + } + return utype_category_names[ category ]; +} + +/*@ + * @brief Get the value of a flag. + * + * This method returns the value of a flag based on the + * text string given. This is used during ruleset parsing + * to assign values to category flags. + */ +unsigned +utype_get_flag_value( const char *flag ) +{ + unsigned i = 0; + + while( utype_flag_values[ i ].name ) + { + if( !strcmp( flag, utype_flag_values[ i ].name ) ) + { + return utype_flag_values[ i ].value; + } + i++; + } + return 0; +} + +/*@ + * @brief Add a caapbility to a unit. + * + * Set a flag in the capability vector of the specified + * unit. + * + * @param punit A pointer to the unit to test. + * @param cat The category id of the capab to add. + * @param capab The capab to add. + */ +void +utype_add_capab( struct unit_type *ptype, + enum utype_category cat, + unsigned capab ) +{ + ptype->flag_set[ cat ] |= capab; +} + +/*@ + * @brief Test a unit for subscription to a flag. + * + * This method is used to test a unit for subscription to + * a subset of flags set. A category is specified to lookup + * the flag set. Only flags from one category may be tested + * per call. + * + * @param punit A pointer to the unit to test. + * @param cat The category id of the flag set to test. + * @param capab An integer representing the flags to test + * for. + * @return 1 if the flags are set, 0 otherwise. + */ +int +utype_has_capab( struct unit_type *ptype, + enum utype_category cat, + unsigned capab ) +{ + return ptype->flag_set[ cat ] & capab; +} Index: common/unittype.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/unittype.h,v retrieving revision 1.7 diff -u -r1.7 unittype.h --- common/unittype.h 2001/09/15 15:31:25 1.7 +++ common/unittype.h 2001/12/05 17:33:15 @@ -143,18 +143,128 @@ L_LAST }; +/*@ + * @brief Enumeration of category ids. + * + * The unit_category_id enumeration describes the identifiers + * of the set of categories used to describe properties of a + * unit. Each category defines a subset of identifiable properties + * of a unit. Each category is represented by a 32 bit field + * that uses bit flags to represent values for each possible + * value. + * + * Under this model, a unit essentially subscribes to properties + * in each category. For example, a combat unit can both bomb + * and perform tactical strikes. A hover craft should be able to + * travel over both land and sea. + * + * This model gains three benifits over the previous information + * model. First, it localizes all basic unit informaiton into a + * single attribute. Secondly, it provides a much more extensible + * model for defining unit capabilities, and finally, with the + * extended bit space, it allows individual definition of + * capabilities instead of grouping capabilties as before. + * + * Values of these categories are actually defined as bits, not + * as enums that are shifted to bit values. + * + * The integer value of the unit_category id corresponds to the + * index of an array in the unit_flags value. + */ +enum utype_category +{ + CAT_MOVE, /*@< Movement */ + CAT_CLASS, /*@< Basic unit type */ + CAT_ATTACK, /*@< Combat capabilities */ + CAT_TRANSPORT, /*@< Transport capabilities */ + CAT_BUILD, /*@< Construction */ + CAT_IMPROVE, /*@< Improvements */ + CAT_INTEL, /*@< Diplomacy and spying */ + CAT_LAST /*@< Unused */ +}; + +/*@ + * @brief Specification of the unit_flags type. + * + * The unit_flags type is an array of unsigned integers. Each + * index of the array corresponds to a unit_category and each + * value within the array contains a 32 bit flag field. + */ +typedef unsigned utype_flags[ CAT_LAST ]; + +/* movement class flags */ +#define CAPAB_MOVE_LAND 0x01 +#define CAPAB_MOVE_SEA 0x02 +#define CAPAB_MOVE_HOVER 0x03 +#define CAPAB_MOVE_RANGED 0x07 +#define CAPAB_MOVE_ORBIT 0x0f + +/* combat class flags */ +#define CAPAB_PIKEMEN 0x01 +#define CAPAB_HORSE 0x02 + +/* combat operations flags */ +#define CAPAB_ATTACK_MELEE 0x01 +#define CAPAB_ATTACK_BOMBARD 0x02 +#define CAPAB_ATTACK_BOMB 0x04 +#define CAPAB_ATTACK_NUKE 0x08 + +/* transport options */ +#define CAPAB_TRANSPORT_ANY 0x01 + +/* construction operation flags */ +#define CAPAB_BUILD_CITY 0x01 +#define CAPAB_BUILD_FORTRESS 0x02 +#define CAPAB_BUILD_AIRBASE 0x04 +#define CAPAB_BUILD_COLONY 0x08 + +/* improvment operation flags */ +#define CAPAB_IMPROVE_IRRIGATE 0x01 +#define CAPAB_IMPROVE_MINE 0x02 +#define CAPAB_IMPROVE_ROAD 0x04 +#define CAPAB_IMPROVE_RAIL 0x08 + +/* inteligence operations */ +#define CAPAB_INTEL_EMBASSY 0x01 +#define CAPAB_INTEL_BRIBE 0x02 +#define CAPAB_INTEL_SABOTAGE 0x04 +#define CAPAB_INTEL_STEAL 0x08 +#define CAPAB_INTEL_INCITE 0x10 +#define CAPAB_INTEL_MOVE 0x20 +#define CAPAB_INTEL_POISON 0x01 + +/*@ + * @brief Type information for a unit. + * + * The unit_type structure encapsulates information about + * a type of unit. There is one unit_type instance for \e type + * of unit (as opposed to per unit). + * + * @todo Need better descriptions of some fields. + */ struct unit_type { - char name[MAX_LEN_NAME]; - char name_orig[MAX_LEN_NAME]; /* untranslated */ + char name[MAX_LEN_NAME]; /*@< Name of unit */ + char name_orig[MAX_LEN_NAME]; /*@< Untranslated - what is this? */ + + /* graphics information */ char graphic_str[MAX_LEN_NAME]; char graphic_alt[MAX_LEN_NAME]; struct Sprite *sprite; + enum unit_move_type move_type; int build_cost; - int pop_cost; /* number of workers the unit contains (e.g., settlers, engineers)*/ - int attack_strength; - int defense_strength; - int move_rate; + + /*@ + * Number of workers the unit contains (e.g., settlers, engineers) + * + * @todo This needs a more thorough explanation. + */ + int pop_cost; + + int attack_strength; /*@< Attack rating of unit. */ + int defense_strength; /*@< Defense rating of unit. */ + int move_rate; /*@< Number of moves. */ + int tech_requirement; int vision_range; int transport_capacity; @@ -163,22 +273,28 @@ int obsoleted_by; int fuel; - unsigned int flags; + unsigned int flags; /*@< Obsolete */ unsigned int roles; + + utype_flags flag_set; /*@< Set of flags for unit type */ - int happy_cost; /* unhappy people in home city */ - int shield_cost; /* normal upkeep cost */ - int food_cost; /* settler food cost */ - int gold_cost; /* gold upkeep (n/a now, maybe later) */ + int happy_cost; /*@< Unhappy people in home city */ + int shield_cost; /*@< Normal upkeep cost */ + int food_cost; /*@< Unit food cost */ + int gold_cost; /*@< Gold upkeep (n/a now, maybe later) */ - int paratroopers_range; /* only valid for F_PARATROOPERS */ + int paratroopers_range; /*@< only valid for F_PARATROOPERS */ int paratroopers_mr_req; int paratroopers_mr_sub; + /*@ + * The helptext field defines in game help for the unit. + * This is displayed in the online help browser when the unit + * is queried for help. + */ char *helptext; }; - extern struct unit_type unit_types[U_LAST]; int unit_type_exists(Unit_Type_id id); @@ -227,5 +343,81 @@ int num_role_units(int role); Unit_Type_id get_role_unit(int role, int index); Unit_Type_id best_role_unit(struct city *pcity, int role); + +/* extended unit flag test */ +/* configuration interface */ +const char *utype_get_category_name( enum utype_category ); +unsigned utype_get_flag_value( const char * ); + +/* caapbility interface interface */ +void utype_add_capab( struct unit_type *, + enum utype_category, + unsigned ); +int utype_has_caapb( struct unit_type *, + enum utype_category, + unsigned ); + +/*@ + * @def CAPAB_MOVE_LAND + * Units with this property can travel over land. + * + * @def CAPAB_MOVE_SEA + * Units with this property can travel over sea. + * + * @def CAPAB_MOVE_HOVER + * Hovering units can move over land or sea without restriction. + * + * @def CAPAB_MOVE_RANGED + * Units with a ranged travel capability have a limited + * distance they can move in one turn. Units with this capability + * typically have a fuel parameter associated with them. + * + * @def CAPAB_MOVE_ORBIT + * Units capable of orbital travel can go to any tile on + * the map in a single turn. + * + * @def CAPAB_PIKEMEN + * @def CAPAB_HORSE + * + * @def CAPAB_ATTACK_MELEE + * Units with this flag set can participate in melee combat. + * If a unit does not define this flag, then it cannot perform + * melee attack (e.g. settlers). Units without this flag will + * be captured without a fight if they are attacked in a melee. + * + * @def CAPAB_ATTACK_BOMBARD + * Units with this flag set are capable of bombarding enemy + * units. A bombard attack allows the attacker to attack from + * some range. Enemy units passing within the bombard range + * of a bombard unit shall be bombarded without cost to the + * bombarding unit. + * + * @def CAPAB_ATTACK_BOMB + * @def CAPAB_ATTACK_NUKE + * + * @def CAPAB_TRANSPORT_ANY + * Units with this flag set are capable of transport + * any land units. + * + * @def CAPAB_BUILD_CITY + * @def CAPAB_BUILD_FORTRESS + * @def CAPAB_BUILD_AIRBASE + * @def CAPAB_IMPROVE_IRRIGATE + * @def CAPAB_IMPROVE_MINE + * @def CAPAB_IMPROVE_ROAD + * @def CAPAB_IMPROVE_RAIL + * @def CAPAB_INTEL_EMBASSY + * + * @def CAPAB_INTEL_BRIBE + * This capability allows a unit to bribe enemy units, bringing + * them onto the bribing units side. + * @todo Should this be an attack? + * + * @def CAOAB_INTEL_SABOTAGE + * @def CAPAB_INTEL_STEAL + * @def CAPAB_INTEL_INCITE + * @def CAPAB_INTEL_MOVE + * @def CAPAB_INTEL_POISON + */ #endif /* FC__UNITTYPE_H */ Index: data/default/units.ruleset =================================================================== RCS file: /home/freeciv/CVS/freeciv/data/default/units.ruleset,v retrieving revision 1.28 diff -u -r1.28 units.ruleset --- data/default/units.ruleset 2001/08/29 16:11:50 1.28 +++ data/default/units.ruleset 2001/12/05 17:33:16 @@ -82,6 +82,8 @@ uk_food = 1 uk_gold = 0 flags = "Settlers", "NonMil", "Airbase", "AddToCity", "Cities" +capab_move = "move_land" +capab_build = "build_city", "build_airbase", "build_fortress", "build_colony" roles = "" helptext = _("\ Settlers are one of the key units in the game. They can be used to\ Index: server/ruleset.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v retrieving revision 1.82 diff -u -r1.82 ruleset.c --- server/ruleset.c 2001/10/26 07:33:23 1.82 +++ server/ruleset.c 2001/12/05 17:33:19 @@ -598,11 +598,15 @@ { char *datafile_options; struct unit_type *u; - int i, j, ival, nval; + int i, j, k, ival, nval; int max_hp, max_firepower; char *sval, **slist, **sec; const char *filename = secfile_filename(file); + int n_flags; /* number of flags */ + char **flags; /* list of names for flags */ + const char *name; /* used to get category names */ + datafile_options = check_ruleset_capabilities(file, "+1.9", filename); @@ -613,6 +617,7 @@ game.firepower_factor = secfile_lookup_int_default(file, 1, "units_adjust.firepower_factor"); + /* get the names of all the unit sections in the ruleset */ sec = secfile_get_secnames_prefix(file, "unit_", &nval); /* Tech requirement is used to flag removed unit_types, which @@ -733,6 +738,53 @@ } } free(slist); + + /* extended category/flag selection */ + /* this works a little differently than the rest of the ruleset + * parsing stuff. it iterates thru all possible category id's + * and looks up the name of the specifc category for each unit. + */ + for( i = 0; i < game.num_unit_types; i++ ) { + u = &unit_types[ i ]; + + /* set the flag set to empty for all categories */ + memset( u->flag_set, 0, sizeof( utype_flags ) ); + + /* + * iterate thru known categories and get the config + * directive for each. + */ + for( j = 0; j < CAT_LAST; j++ ) { + /* get the category name */ + name = utype_get_category_name( j ); + + /* + * get the configuration value for the category. + * this lookup is for .. + * this should return a vector of flags + */ + n_flags = 0; + flags = secfile_lookup_str_vec( file, + &n_flags, + "%s.%s", + sec[ i ], + name ); + if( !flags ) { + /* this is okay. flags haven't been defined */ + continue; + } + else { + for( k = 0; k < n_flags; k++ ) { + unsigned flag = utype_get_flag_value( flags[ k ] ); + utype_add_capab(u, j, flag ); + } + + /* free the flag list */ + free( flags ); + } + + } + } } /* roles */