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

 This introduces several new base related helper functions hiding the
fact that bases are actually bits in specials bitvector. Used them
where appropriate.

 Applies on top of #34081 and #34205, currently untested


 - ML

diff -Nurd -X.diff_ignore freeciv/client/tilespec.c freeciv/client/tilespec.c
--- freeciv/client/tilespec.c	2006-07-25 13:42:32.000000000 +0300
+++ freeciv/client/tilespec.c	2007-01-22 22:00:58.000000000 +0200
@@ -3929,6 +3929,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. */
@@ -4047,7 +4052,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);
       }
@@ -4101,7 +4107,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);
       }
 
@@ -4150,7 +4157,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-22 21:03:07.000000000 +0200
+++ freeciv/common/base.c	2007-01-22 21:11:21.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-22 21:03:07.000000000 +0200
+++ freeciv/common/base.h	2007-01-22 21:27:51.000000000 +0200
@@ -14,6 +14,7 @@
 #define FC__BASE_H
 
 #include "fc_types.h"
+#include "terrain.h"
 
 enum base_type_id { BASE_FORTRESS = 0, BASE_AIRBASE, BASE_LAST };
 
@@ -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-22 21:03:07.000000000 +0200
+++ freeciv/common/terrain.c	2007-01-22 21:55:38.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-22 21:03:02.000000000 +0200
+++ freeciv/common/tile.c	2007-01-22 21:49:51.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 */
+    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-22 21:50:47.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-22 17:18:36.000000000 +0200
+++ freeciv/common/unit.c	2007-01-22 21:36:26.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-22 21:50:07.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-22 21:03:02.000000000 +0200
+++ freeciv/server/unittools.c	2007-01-22 21:57:36.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

Reply via email to