Complete.Org: Mailing Lists: Archives: freeciv-dev: July 2003:
[Freeciv-Dev] Re: (PR#4710) introduce map topology check macros
Home

[Freeciv-Dev] Re: (PR#4710) introduce map topology check macros

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] Re: (PR#4710) introduce map topology check macros
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 28 Jul 2003 21:43:43 -0700
Reply-to: rt@xxxxxxxxxxxxxx

rwetmore@xxxxxxxxxxxx wrote:
> I suspect this is unnecessarily verbose and non-generalized for something
> that is supposed to be part of a gen-topology implementation.
> 
>    map_hasFlag(<one of the topology flag enums>)
> 
> is a single macro that does it all, will be just as easy to read in code
> and doesn't hardcode specific topology features in a function name keeping
> the API interface to a minimum and making it easy to update over time.
> 
> Minor style nit, but keeps things data-driven vs locking in hardcoded names.

In the corecleanups you have

   enum MAP_TYPE {
     MAP_TYPE_FLAT    = 0,  /* Note: not a WRAPTYPE */
     MAP_TYPE_WRAPX   = 1,
     MAP_TYPE_WRAPY   = 2,
     MAP_TYPE_TORUS   = 3,
     MAP_TYPE_ISO     = 4,  /* map is stored in isometric form */
     MAP_TYPE_ISEARTH = 8,  /* map is earth == special type    */
     MAP_TYPE_LAST    = 16
   };

   #define is_maptype(TYPE)        (map_type == (TYPE))
   #define get_maptype(TYPE)       (map_type & (TYPE))
   #define has_mapwrap(WRAPTYPE)   (get_maptype(WRAPTYPE) == (WRAPTYPE))

which I guess is what you consider "data-driven".  The problem is that 
this leads to all sorts of unreadable constructs:

   switch (get_maptype(MAP_TYPE_WRAPX | MAP_TYPE_WRAPY)) {
     case MAP_TYPE_FLAT:

     case MAP_TYPE_WRAPX:

     case MAP_TYPE_WRAPY:

     case MAP_TYPE_TORUS:

   }

which are perfectly logical but make for an awful and bug-prone 
interface - you HAVE to know how the backend works in order to use the 
interface properly.  As another example you can have

   if (get_maptype(MAP_TYPE_TORUS)) {

   }

versus

   if (has_mapwrap(MAP_TYPE_TORUS)) {

   }

versus

   if (is_maptype(MAP_TYPE_TORUS)) {

   }

which are quite different in very unintuitive ways.


My alternative is to keep the interface very simple - three macros 
returning only boolean values.  The backend interface can do whatever it 
wants - bitfields are the most likely since we aim to have a single 
value representing the topology ID.


The basic problem with your system is that MAP_TYPE_TORUS (or any | 
combination of flags) is a map type and cannot intuitively be used as a 
flag value.  But because the interface does not make this distinction 
there is a problem.  To keep the interface simple the callers should 
only use three forms:

   has_mapwrap(MAP_TYPE_WRAPX)
   has_mapwrap(MAP_TYPE_WRAPY)
   has_mapwrap(MAP_TYPE_ISO)

which return boolean values.  But if you do that, why not make the 
complete separation between interface and backend and just have three 
separate macros?

jason




[Prev in Thread] Current Thread [Next in Thread]