<URL: http://bugs.freeciv.org/Ticket/Display.html?id=34336 >
On 1/22/07, Marko Lindqvist <[EMAIL PROTECTED]> wrote: > > This introduces several new base related helper functions hiding the > fact that bases are actually bits in specials bitvector. Used them > where appropriate. Fixed a bug that tile_has_base_flag() never returned TRUE. - ML
diff -Nurd -X.diff_ignore freeciv/client/tilespec.c freeciv/client/tilespec.c --- freeciv/client/tilespec.c 2007-01-22 22:58:41.000000000 +0200 +++ freeciv/client/tilespec.c 2007-01-26 11:43:19.000000000 +0200 @@ -3932,6 +3932,11 @@ int tileno, dir; struct drawn_sprite *save_sprs = sprs; struct player *owner = NULL; + struct base_type *pbase = NULL; + + if (ptile != NULL) { + pbase = tile_get_base(ptile); + } /* Unit drawing is disabled if the view options is turned off, but only * if we're drawing on the mapview. */ @@ -4050,7 +4055,8 @@ } } - if (draw_fortress_airbase && contains_special(tspecial, S_FORTRESS) + if (draw_fortress_airbase + && pbase != NULL && pbase->id == BASE_FORTRESS && t->sprites.tx.fortress_back) { ADD_SPRITE_FULL(t->sprites.tx.fortress_back); } @@ -4104,7 +4110,8 @@ case LAYER_SPECIAL2: if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) { - if (draw_fortress_airbase && contains_special(tspecial, S_AIRBASE)) { + if (draw_fortress_airbase + && pbase != NULL && pbase->id == BASE_AIRBASE) { ADD_SPRITE_FULL(t->sprites.tx.airbase); } @@ -4153,7 +4160,7 @@ case LAYER_SPECIAL3: if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) { if (t->is_isometric && draw_fortress_airbase - && contains_special(tspecial, S_FORTRESS)) { + && pbase != NULL && pbase->id == BASE_FORTRESS) { /* Draw fortress front in iso-view (non-iso view only has a fortress * back). */ ADD_SPRITE_FULL(t->sprites.tx.fortress); diff -Nurd -X.diff_ignore freeciv/common/base.c freeciv/common/base.c --- freeciv/common/base.c 2007-01-26 12:14:27.000000000 +0200 +++ freeciv/common/base.c 2007-01-26 12:16:49.000000000 +0200 @@ -43,6 +43,21 @@ return pbase->name; } +/**************************************************************************** + Determine base type from specials. Returns NULL if there is no base +****************************************************************************/ +struct base_type *base_type_get_from_special(bv_special spe) +{ + if (contains_special(spe, S_FORTRESS)) { + return base_type_get_by_id(BASE_FORTRESS); + } + if (contains_special(spe, S_AIRBASE)) { + return base_type_get_by_id(BASE_AIRBASE); + } + + return NULL; +} + /************************************************************************** Convert base flag names to enum; case insensitive; returns BF_LAST if can't match. diff -Nurd -X.diff_ignore freeciv/common/base.h freeciv/common/base.h --- freeciv/common/base.h 2007-01-26 12:14:27.000000000 +0200 +++ freeciv/common/base.h 2007-01-26 12:05:42.000000000 +0200 @@ -14,14 +14,15 @@ #define FC__BASE_H #include "fc_types.h" +#include "terrain.h" enum base_type_id { BASE_FORTRESS = 0, BASE_AIRBASE, BASE_LAST }; typedef enum base_type_id Base_type_id; enum base_flag_id { - BF_NOT_AGGRESSIVE, /* Unit inside are not considered aggressive - * if base is close to city */ + BF_NOT_AGGRESSIVE = 0, /* Unit inside are not considered aggressive + * if base is close to city */ BF_DEFENSE_BONUS, /* Base provides defense bonus for units inside */ BF_NO_STACK_DEATH, /* Units inside will not die all at once */ BF_WATCHTOWER, /* Base can act as watchtower */ @@ -46,6 +47,8 @@ bool base_flag(const struct base_type *pbase, enum base_flag_id flag); const char *base_name(const struct base_type *pbase); +struct base_type *base_type_get_from_special(bv_special spe); + enum base_flag_id base_flag_from_str(const char *s); struct base_type *base_type_get_by_id(Base_type_id id); diff -Nurd -X.diff_ignore freeciv/common/terrain.c freeciv/common/terrain.c --- freeciv/common/terrain.c 2007-01-26 12:14:27.000000000 +0200 +++ freeciv/common/terrain.c 2007-01-26 11:43:19.000000000 +0200 @@ -468,6 +468,7 @@ { static char s[256]; char *p; + struct base_type *pbase; s[0] = '\0'; @@ -489,12 +490,10 @@ cat_snprintf(s, sizeof(s), "%s/", _("Mine")); } - if (contains_special(spe, S_FORTRESS)) { - cat_snprintf(s, sizeof(s), "%s/", base_name(base_type_get_by_id(BASE_TYPE_1))); - } + pbase = base_type_get_from_special(spe); - if (contains_special(spe, S_AIRBASE)) { - cat_snprintf(s, sizeof(s), "%s/", base_name(base_type_get_by_id(BASE_TYPE_2))); + if (pbase != NULL) { + cat_snprintf(s, sizeof(s), "%s/", base_name(pbase)); } p = s + strlen(s) - 1; diff -Nurd -X.diff_ignore freeciv/common/tile.c freeciv/common/tile.c --- freeciv/common/tile.c 2007-01-26 12:14:23.000000000 +0200 +++ freeciv/common/tile.c 2007-01-26 12:10:17.000000000 +0200 @@ -17,6 +17,7 @@ #include <assert.h> +#include "log.h" #include "support.h" #include "tile.h" @@ -99,14 +100,59 @@ } /**************************************************************************** + Returns base at tile or NULL if no base +****************************************************************************/ +struct base_type *tile_get_base(const struct tile *ptile) +{ + return base_type_get_from_special(ptile->special); +} + +/**************************************************************************** + Adds base to tile. + FIXME: Currently this asserts that tile contains no old base. + Instead should remove old base and return bool indicating that. +****************************************************************************/ +void tile_add_base(struct tile *ptile, const struct base_type *pbase) +{ + assert(pbase != NULL); + + if (pbase->id == BASE_FORTRESS) { + assert(!tile_has_special(ptile, S_AIRBASE)); + tile_set_special(ptile, S_FORTRESS); + } else if (pbase->id == BASE_AIRBASE) { + assert(!tile_has_special(ptile, S_FORTRESS)); + tile_set_special(ptile, S_AIRBASE); + } else { + freelog(LOG_ERROR, "Impossible base type %d in tile_set_base()", + pbase->id); + } +} + +/**************************************************************************** + Removes base from tile if such exist +****************************************************************************/ +void tile_remove_base(struct tile *ptile) +{ + tile_clear_special(ptile, S_FORTRESS); + tile_clear_special(ptile, S_AIRBASE); +} + +/**************************************************************************** Check if tile contains base providing effect ****************************************************************************/ 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_get_by_id(BASE_FORTRESS), flag)) - || (tile_has_special(ptile, S_AIRBASE) - && base_flag(base_type_get_by_id(BASE_AIRBASE), flag)); + struct base_type *pbase; + + pbase = tile_get_base(ptile); + + if (pbase != NULL) { + /* Some base at tile, check its flags */ + return base_flag(pbase, flag); + } + + /* No base at tile */ + return FALSE; } /**************************************************************************** diff -Nurd -X.diff_ignore freeciv/common/tile.h freeciv/common/tile.h --- freeciv/common/tile.h 2007-01-22 17:18:36.000000000 +0200 +++ freeciv/common/tile.h 2007-01-26 11:43:19.000000000 +0200 @@ -63,6 +63,9 @@ enum tile_special_type to_test_for); bool tile_has_any_specials(const struct tile *ptile); void tile_set_special(struct tile *ptile, enum tile_special_type spe); +struct base_type *tile_get_base(const struct tile *ptile); +void tile_add_base(struct tile *ptile, const struct base_type *pbase); +void tile_remove_base(struct tile *ptile); bool tile_has_base_flag(const struct tile *ptile, enum base_flag_id flag); const struct resource *tile_get_resource(const struct tile *ptile); void tile_set_resource(struct tile *ptile, const struct resource *presource); diff -Nurd -X.diff_ignore freeciv/common/unit.c freeciv/common/unit.c --- freeciv/common/unit.c 2007-01-25 17:59:51.000000000 +0200 +++ freeciv/common/unit.c 2007-01-26 11:43:19.000000000 +0200 @@ -726,6 +726,7 @@ { struct player *pplayer = unit_owner(punit); struct terrain *pterrain = ptile->terrain; + struct base_type *pbase; switch(activity) { case ACTIVITY_IDLE: @@ -815,16 +816,18 @@ return FALSE; case ACTIVITY_FORTRESS: + pbase = tile_get_base(ptile); return (unit_flag(punit, F_SETTLERS) && !tile_get_city(ptile) && player_knows_techs_with_flag(pplayer, TF_FORTRESS) - && !tile_has_special(ptile, S_FORTRESS) + && (pbase == NULL || pbase->id != BASE_FORTRESS) && !is_ocean(ptile->terrain)); case ACTIVITY_AIRBASE: + pbase = tile_get_base(ptile); return (unit_flag(punit, F_AIRBASE) && player_knows_techs_with_flag(pplayer, TF_AIRBASE) - && !tile_has_special(ptile, S_AIRBASE) + && (pbase == NULL || pbase->id != BASE_AIRBASE) && !is_ocean(ptile->terrain)); case ACTIVITY_SENTRY: diff -Nurd -X.diff_ignore freeciv/server/citytools.c freeciv/server/citytools.c --- freeciv/server/citytools.c 2007-01-22 17:18:36.000000000 +0200 +++ freeciv/server/citytools.c 2007-01-26 11:43:20.000000000 +0200 @@ -1009,8 +1009,7 @@ /* Put vision back to normal, if base acted as a watchtower */ if (tile_has_base_flag(ptile, BF_WATCHTOWER)) { - tile_clear_special(ptile, S_FORTRESS); - tile_clear_special(ptile, S_AIRBASE); + tile_remove_base(ptile); unit_list_refresh_vision(ptile->units); } diff -Nurd -X.diff_ignore freeciv/server/unittools.c freeciv/server/unittools.c --- freeciv/server/unittools.c 2007-01-26 12:14:23.000000000 +0200 +++ freeciv/server/unittools.c 2007-01-26 11:43:20.000000000 +0200 @@ -707,6 +707,9 @@ punit->activity_target) >= 1) { enum tile_special_type what_pillaged = punit->activity_target; + /* FIXME: If pillaging some kind of base, should not + * touch specials directly but to use base related + * functions. */ tile_clear_special(ptile, what_pillaged); unit_list_iterate (ptile->units, punit2) { if ((punit2->activity == ACTIVITY_PILLAGE) && @@ -743,7 +746,7 @@ if (activity == ACTIVITY_FORTRESS) { if (total_activity (ptile, ACTIVITY_FORTRESS) >= tile_activity_time(ACTIVITY_FORTRESS, ptile)) { - tile_set_special(ptile, S_FORTRESS); + tile_add_base(ptile, base_type_get_by_id(BASE_FORTRESS)); map_claim_ownership(ptile, unit_owner(punit), ptile); unit_activity_done = TRUE; new_base = TRUE; @@ -753,7 +756,7 @@ if (activity == ACTIVITY_AIRBASE) { if (total_activity (ptile, ACTIVITY_AIRBASE) >= tile_activity_time(ACTIVITY_AIRBASE, ptile)) { - tile_set_special(ptile, S_AIRBASE); + tile_add_base(ptile, base_type_get_by_id(BASE_AIRBASE)); unit_activity_done = TRUE; new_base = TRUE; } @@ -1250,13 +1253,11 @@ { int cap; struct player_tile *plrtile = map_get_player_tile(ptile, pplayer); + struct base_type *pbase = base_type_get_from_special(plrtile->special); if ((is_allied_city_tile(ptile, pplayer) && !is_non_allied_unit_tile(ptile, pplayer)) - || (((contains_special(plrtile->special, S_FORTRESS) - && base_flag(base_type_get_by_id(BASE_FORTRESS), BF_REFUEL)) - || (contains_special(plrtile->special, S_AIRBASE) - && base_flag(base_type_get_by_id(BASE_AIRBASE), BF_REFUEL))) + || ((pbase != NULL && base_flag(pbase, 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